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
相关产品推荐
相关产品推荐

