NextAuth无法获取JWT Token,JWT回调断点未触发求助
问题排查与解决
核心原因:Session策略未配置为JWT
当使用FirestoreAdapter(数据库适配器)时,NextAuth默认的session.strategy为database模式。这种模式下会话数据存储在数据库中,jwt回调不会自动触发——系统无需通过JWT解析会话信息,这就是你观察到jwt回调未执行的根本原因。
解决步骤
1. 添加Session策略配置
在NextAuth配置中显式设置session.strategy: "jwt",强制使用JWT模式处理会话,确保jwt回调正常触发:
export default NextAuth({ // ... 其他配置项 session: { strategy: "jwt", // 必须配置此项 maxAge: 30 * 24 * 60 * 60, // 可选:会话过期时间,默认30天 }, // ... callbacks等后续配置 })
2. 修正Session回调的参数与逻辑
你的session回调参数结构错误,正确参数为({ session, token });同时需要将jwt中的Token数据注入session对象,才能在SSR中获取到有效内容:
callbacks: { // ... signIn、jwt回调代码 session: async ({ session, token }) => { // 将jwt中的用户信息、Token挂载到session session.user = token.user; session.accessToken = token.accessToken; return session; }, }
3. 修正Secret环境变量
避免使用NEXT_PUBLIC_前缀的环境变量作为NextAuth的secret——这类变量会暴露给前端,存在安全风险。建议改用后端专用变量名,比如NEXTAUTH_SECRET:
secret: process.env.NEXTAUTH_SECRET,
4. 清理冗余Provider配置
GoogleProvider默认会返回idToken,无需额外配置idToken: true,可直接移除该字段。
完整修正后的配置片段
export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET, checks: ["pkce", "state"], async profile(profile) { return { id: profile.sub, name: profile.name, email: profile.email, email_verified: profile.email_verified } }, }), ], pages: { signIn: '/auth/signin', signOut: '/auth/signout', error: '/auth/error' }, secret: process.env.NEXTAUTH_SECRET, session: { strategy: "jwt", }, adapter: FirestoreAdapter({ apiKey: process.env.FIREBASE_API_KEY, appId: process.env.FIREBASE_APP_ID, authDomain: process.env.FIREBASE_AUTH_DOMAIN, databaseURL: process.env.FIREBASE_DATABASE_URL, projectId: process.env.FIREBASE_PROJECT_ID, storageBucket: process.env.FIREBASE_STORAGE_BUCKET, messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID }), callbacks: { async signIn({ account, profile }) { if (account.provider === "google") { return profile.email_verified } return false }, jwt: async({ token, user, account }) => { if (account && user) { return { accessToken: account.access_token, accessTokenExpires: Date.now() + account.expires_in * 1000, refreshToken: account.refresh_token, user } } if (Date.now() < token.accessTokenExpires) { return token } return refreshAccessToken(token) }, session: async ({ session, token }) => { session.user = token.user; session.accessToken = token.accessToken; return session; }, }, })
内容的提问来源于stack exchange,提问作者hammies
相关产品推荐
相关产品推荐

