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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:25:19