You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:15:43