使用Passport Steam更新Supabase Profiles表的用户SteamID
问题描述
我想更新Supabase的profiles表,写入用户的SteamID。思路是在Passport Steam策略中获取Supabase用户对象,再通过Supabase JavaScript客户端库更新表,但实现后要么返回undefined要么报错。
当前策略代码
passport.use( new SteamStrategy( { returnURL: `${process.env.DOMAIN}/api/auth/return`, realm: `${process.env.DOMAIN}`, apiKey: `${process.env.STEAM_API_KEY}`, passReqToCallback: true, // <-- 将请求对象传递给回调函数 passResToCallback: true, // <-- 将响应对象传递给回调函数 passReqRes: true, // <-- 将请求和响应对象传递给回调函数 }, async ( req: NextApiRequest, res: NextApiResponse, _: string, profile: SteamProfile, done: (a: null | string, b: SteamProfile) => typeof done, ) => { const supabaseServerClient = createServerSupabaseClient<Database>({ req, res, }); const { data: { user }, } = await supabaseServerClient.auth.getUser(); console.log(user?.id) console.log(profile.id) return done(null, profile); } ) );
这段代码能在控制台打印出Supabase用户ID,但profile.id是undefined,同时出现以下两个错误:
错误1
TypeError: context.res.getHeader is not a function at setCookie (/var/task/node_modules/.pnpm/@supabase+auth-helpers-nextjs@0.6.0_7jdpwtii2ojrsp4bzhat4kanty/node_modules/@supabase/auth-helpers-nextjs/dist/index.js:81:73)
错误2
Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: done is not a function","reason":{"errorType":"TypeError","errorMessage":"done is not a function","stack":["TypeError: done is not a function"," at /var/task/.next/server/chunks/166.js:43:12"," at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: done is not a function"," at process.<anonymous> (file:///var/runtime/index.mjs:1188:17)"," at process.emit (node:events:525:35)"," at emit (node:internal/process/promises:149:20)"," at processPromiseRejections (node:internal/process/promises:283:27)"," at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
解决方案
1. 修复done函数类型与调用问题
你的回调里done的类型定义错误,Passport的done函数返回值是void,不是typeof done。同时异步回调里要确保所有操作完成后再调用done,避免Promise未处理:
done: (err: null | Error, user?: SteamProfile) => void
2. 解决profile.id为undefined的问题
passport-steam返回的SteamID通常存在于profile.id或profile._json.steamid,先打印完整profile确认结构:
console.log('完整Steam profile:', profile);
如果类型定义缺失,扩展SteamProfile类型:
interface SteamProfile { id: string; _json: { steamid: string; // 其他字段按需添加 }; }
3. 修复context.res.getHeader错误
- 移除重复的配置项:
passReqToCallback和passResToCallback与passReqRes: true重复,只保留后者即可。 - 若使用Vercel Edge Runtime,升级
@supabase/auth-helpers-nextjs到最新版本,Pages Router下确保API路由在pages/api目录,res是标准NextApiResponse对象。
4. 完整修正代码示例
passport.use( new SteamStrategy( { returnURL: `${process.env.DOMAIN}/api/auth/return`, realm: `${process.env.DOMAIN}`, apiKey: `${process.env.STEAM_API_KEY}`, passReqRes: true, // 仅保留此配置项 }, async ( req: NextApiRequest, res: NextApiResponse, _: string, profile: SteamProfile, done: (err: null | Error, user?: SteamProfile) => void ) => { try { const supabaseServerClient = createServerSupabaseClient<Database>({ req, res }); const { data: { user } } = await supabaseServerClient.auth.getUser(); if (user) { // 兼容两种SteamID获取方式 const steamId = profile.id || profile._json?.steamid; if (steamId) { // 更新profiles表 await supabaseServerClient .from('profiles') .update({ steam_id: steamId }) .eq('id', user.id); } } console.log('Supabase用户ID:', user?.id); console.log('SteamID:', steamId); done(null, profile); } catch (error) { console.error('认证回调错误:', error); done(error as Error); } } ) );
内容的提问来源于stack exchange,提问作者H1GHG2M3R
相关产品推荐
相关产品推荐

