NextAuth集成Azure AD时refresh token生效但session回调token未定义问题
问题解决思路
核心问题出在refreshAccessToken函数的返回值处理上:你的函数在fetch的then链中返回了刷新后的token对象,但外层async函数并未正确捕获这个结果,最终导致函数返回undefined。当jwt回调返回undefined时,session回调中的token参数就会变成undefined,进而触发"cannot read property accessToken from undefined"错误。
修复步骤
1. 修正refreshAccessToken函数
将fetch的链式调用改为await语法,确保函数能正确返回刷新后的token对象:
async function refreshAccessToken(accessToken) { try { const url = "https://login.microsoftonline.com/02cd5db4-6c31-4cb1-881d-2c79631437e8/oauth2/v2.0/token"; const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: `grant_type=refresh_token` + `&client_secret=${process.env.AZURE_AD_CLIENT_SECRET}` + `&refresh_token=${accessToken.refreshToken}` + `&client_id=${process.env.AZURE_AD_CLIENT_ID}` }); const res = await response.json(); return { ...accessToken, accessToken: res.access_token, accessTokenExpires: Date.now() + res.expires_in * 1000, refreshToken: res.refresh_token ?? accessToken.refreshToken, // Fall back to old refresh token }; } catch (error) { console.log(error); return { ...accessToken, error: "RefreshAccessTokenError", }; } }
2. 给jwt回调添加边界判断(可选但更健壮)
在jwt回调中先判断token是否存在,避免初始阶段可能的异常:
async jwt({token, account, profile}) { // 初始登录时设置token数据 if (account && profile) { token.accessToken = account.access_token; token.accessTokenExpires = account.expires_at * 1000; token.refreshToken = account.refresh_token; token.id = profile.oid; token.groups = profile.groups; token.username = profile.preferred_username; return token; } // 如果token不存在或未过期,直接返回 if (!token) return null; if (Date.now() < token.accessTokenExpires) { return token; } return refreshAccessToken(token); }
3. session回调添加容错处理
为避免token为undefined时崩溃,添加简单判断:
async session({session, token}) { if (!token) return session; session.accessToken = token.accessToken; session.user.id = token.id; session.user.groups = token.groups; session.user.username = token.username; const splittedName = session.user.name?.split(" ") || []; session.user.firstName = splittedName.length > 0 ? splittedName[0] : null; session.user.lastName = splittedName.length > 1 ? splittedName[1] : null; return session; }
原理说明
原来的refreshAccessToken中,await fetch之后使用then链式调用,但该链式调用的结果未被外层async函数return,导致函数默认返回undefined。jwt回调返回undefined后,NextAuth不会传递有效token给session回调,最终引发错误。改用await语法后,函数能正确返回刷新后的token对象,jwt回调返回有效token,session回调就能正常获取到token数据。
内容的提问来源于stack exchange,提问作者Wouter Deen
相关产品推荐
相关产品推荐

