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

Next.js 14.2 + next-auth v4.24中间件刷新token报错求助

解决方案

1. 修正getServerSession的调用参数

在Middleware中调用getServerSession时,必须传入request对象和空响应对象(用于适配内部逻辑),否则会因参数缺失触发substring读取未定义值的错误。修改后的中间件代码:

export async function middleware(request: NextRequest) {
  // 必须传入request和空对象作为第二个参数
  const session = await getServerSession(request, {}, authOptions);
  const requestHeaders = new Headers(request.headers);
  
  if (session?.access_token) {
    requestHeaders.set("Authorization", `Bearer ${session.access_token}`);
  }

  return NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });
}

2. 配置authOptions实现自动刷新Token

要让getServerSession自动处理Token过期刷新,需在authOptions中完善JWT和Session回调逻辑:

完整authOptions示例

import type { AuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials"; // 替换为你使用的认证提供商

// 自定义Token刷新函数
async function refreshAccessToken(token: any) {
  try {
    const response = await fetch("你的后端Token刷新接口", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ refresh_token: token.refresh_token }),
    });

    const refreshedTokens = await response.json();
    if (!response.ok) throw refreshedTokens;

    return {
      ...token,
      access_token: refreshedTokens.access_token,
      expires_at: Date.now() + refreshedTokens.expires_in * 1000,
      refresh_token: refreshedTokens.refresh_token ?? token.refresh_token,
    };
  } catch (error) {
    return { ...token, error: "RefreshAccessTokenError" };
  }
}

export const authOptions: AuthOptions = {
  secret: process.env.NEXTAUTH_SECRET, // 必须配置,否则JWT解析失败
  providers: [
    CredentialsProvider({
      // 你的认证逻辑配置
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        // 实现你的用户验证逻辑,返回用户信息及Token
        const res = await fetch("你的登录接口", {
          method: "POST",
          body: JSON.stringify(credentials),
          headers: { "Content-Type": "application/json" },
        });
        const user = await res.json();
        if (res.ok && user) return user;
        return null;
      },
    }),
  ],
  session: { strategy: "jwt" }, // 必须使用JWT策略支持Token刷新
  jwt: {
    async callback({ token, user, account }) {
      // 首次登录时保存Token信息
      if (account && user) {
        return {
          access_token: account.access_token,
          refresh_token: account.refresh_token,
          expires_at: account.expires_at * 1000,
          user,
        };
      }
      // Token未过期直接返回
      if (Date.now() < token.expires_at) return token;
      // Token过期执行刷新
      return await refreshAccessToken(token);
    },
  },
  callbacks: {
    async session({ session, token }) {
      // 将JWT中的Token信息同步到Session
      session.user = token.user;
      session.access_token = token.access_token;
      session.error = token.error;
      return session;
    },
  },
};

3. 额外排查点

如果仍报错,检查以下内容:

  • 确认NEXTAUTH_SECRET环境变量已正确配置,且与认证提供商的密钥一致。
  • 验证refreshAccessToken函数中的接口地址、参数是否与后端刷新接口匹配。
  • 确认登录接口返回的字段包含access_token、refresh_token和expires_at。

内容的提问来源于stack exchange,提问作者Jack Evans

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:57:08