NextAuth结合Auth0认证:Session回调中无法获取Token求助
解决方案
问题分析
核心问题出在两处:
jwt回调未完整存储用户信息与Token有效期,导致后续session回调无法从token中拿到有效数据;signIn回调的参数结构错误,误将profile作为第一个参数,实际该回调接收的是包含user、account等属性的对象,导致Token判断逻辑出错。
修复步骤
1. 完善jwt回调,持久化Token与用户信息
jwt回调是Token逻辑的核心,需在首次登录时存储access_token、用户信息及过期时间,同时处理Token有效期判断:
async jwt({ token, user, account, profile }) { // 首次授权成功,存储核心数据 if (account && user) { return { accessToken: account.access_token, user: { id: profile.sub, name: profile.name, email: profile.email // 按需添加其他用户字段 }, expiresAt: account.expires_at * 1000 // 转换为毫秒时间戳,方便过期判断 }; } // Token未过期则直接返回 if (Date.now() < token.expiresAt) { return token; } // 可在此添加Token刷新逻辑(若Auth0配置了刷新Token) return token; }
2. 修正signIn回调的参数结构
调整参数为正确的对象解构,才能准确获取account.access_token:
async signIn({ user, account, profile }) { if (account?.access_token) { console.log('ACCESS TOKEN!!!!!!!:', account.access_token); return '/apps'; } return true; }
3. 确保session回调正确映射数据
原session回调逻辑本身没问题,但需依赖修正后的jwt回调提供完整的token数据:
session: async ({ session, token }) => { if (token) { session.user = token.user; session.accessToken = token.accessToken; session.error = token.error; } return session; }
前端获取Token并携带到API请求
修改完成后,可通过useSession钩子在前端获取accessToken并携带到请求头:
import { useSession } from 'next-auth/react'; // 组件内使用 const { data: session } = useSession(); // 发起API请求示例 const fetchData = async () => { if (!session?.accessToken) return; const res = await fetch('/api/your-api', { headers: { 'Authorization': `Bearer ${session.accessToken}` } }); const data = await res.json(); };
完整修正后的[...nextauth].js代码
import NextAuth from 'next-auth'; import Auth0Provider from 'next-auth/providers/auth0'; export default NextAuth({ providers: [ Auth0Provider({ clientId: 'pF....H', clientSecret: 'Mh.....vAbQ', issuer: 'https://dev-xceoh....8u8.us.auth0.com', redirectUri: `http://localhost:3000/api/auth/callback/auth0`, idToken: true, token: { params: { audience: 'https://dev-xce.....r8u8.us.auth0.com/api/v2/' } }, authorization: { params: { audience: encodeURI('https://dev-x......r8u8.us.auth0.com/api/v2/') } } }), ], secret: '306.................024', session: { strategy: 'jwt', secret: process.env.NEXTAUTH_SECRET }, jwt: {}, callbacks: { session: async ({ session, token }) => { if (token) { session.user = token.user; session.accessToken = token.accessToken; session.error = token.error; } return session; }, async redirect(url) { if (typeof url === 'string') { return url.startsWith('http://localhost:3000') ? url : 'http://localhost:3000'; } else { return 'http://localhost:3000'; } }, async jwt({ token, user, account, profile }) { if (account && user) { return { accessToken: account.access_token, user: { id: profile.sub, name: profile.name, email: profile.email, }, expiresAt: account.expires_at * 1000, }; } if (Date.now() < token.expiresAt) { return token; } return token; }, async signIn({ user, account, profile }) { if (account?.access_token) { console.log('ACCESS TOKEN!!!!!!!:', account.access_token); return '/apps'; } return true; }, }, });
内容的提问来源于stack exchange,提问作者siderra
相关产品推荐
相关产品推荐

