使用NextAuth+TwitterProvider+FirestoreAdapter无法获取Twitter用户名
解决NextAuth + Twitter Provider v2无法获取Screen Name(Handle)并添加到Session的问题
你遇到的核心问题是Twitter API v2默认不会返回用户的screen_name(即@handle),需要显式配置Provider的权限和用户信息端点来获取这个字段。以下是完整的修改方案:
1. 调整Twitter Provider配置
在TwitterProvider中添加scope和自定义userinfoEndpoint,请求包含username字段(Twitter v2中screen_name对应字段是username):
providers: [ TwitterProvider({ clientId: process.env.TWITTER_AUTH_CLIENTID, clientSecret: process.env.TWITTER_AUTH_CLIENTSECRET, version: '2.0', // 添加这两行配置 scope: 'users.read', userinfoEndpoint: 'https://api.twitter.com/2/users/me?user.fields=username', }), ],
2. 在JWT回调中存储Screen Name
修改callbacks.jwt,将获取到的username存入token,确保会话中能拿到该字段:
callbacks: { async jwt({ token, profile }) { // 登录时从profile中获取username并存入token if (profile?.username) { token.screenName = profile.username; } return token; }, session: ({ session, token }) => { return { ...session, user: { ...session.user, id: token.sub!, // 从token中取出screenName添加到session用户信息里 screenName: token.screenName, }, } }, },
3. 在CreateUser事件中存储Screen Name到Firestore
修改events.createUser,直接从登录时拿到的profile参数中获取username并写入Firestore:
events: { createUser: async ({ user, profile }) => { const ref = admin .firestore() .collection(Constants.UsersTable) .doc(user.id) await ref.set( { screenName: profile.username, daily_target: 0, onboarded: false, }, { merge: true } ) }, },
完整修改后的代码
export const authOptions: NextAuthOptions = { session: { strategy: 'jwt', }, adapter: FirestoreAdapter(firebaseConfig), pages: { signIn: '/sign-in', }, callbacks: { async jwt({ token, profile }) { if (profile?.username) { token.screenName = profile.username; } return token; }, session: ({ session, token }) => { return { ...session, user: { ...session.user, id: token.sub!, screenName: token.screenName, }, } }, }, events: { createUser: async ({ user, profile }) => { const ref = admin .firestore() .collection(Constants.UsersTable) .doc(user.id) await ref.set( { screenName: profile.username, daily_target: 0, onboarded: false, }, { merge: true } ) }, }, providers: [ TwitterProvider({ clientId: process.env.TWITTER_AUTH_CLIENTID, clientSecret: process.env.TWITTER_AUTH_CLIENTSECRET, version: '2.0', scope: 'users.read', userinfoEndpoint: 'https://api.twitter.com/2/users/me?user.fields=username', }), ], }
关键说明
- Twitter API v2中,原
screen_name字段改名为username,需要通过user.fields=username参数显式请求 - 必须添加
users.read权限才能获取用户的基本信息 - 由于你使用JWT会话策略,需要在JWT回调中持久化screen name,才能在session回调中传递到前端
内容的提问来源于stack exchange,提问作者Norbert Hüthmayr
相关产品推荐
相关产品推荐

