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

NextAuth中Refresh Token安全处理及AccessToken刷新方案咨询

解决NextAuth中Refresh Token安全存储与自动刷新问题

针对你的场景,核心思路是把Refresh Token仅存储在NextAuth服务端的JWT中,绝不暴露给客户端,同时利用NextAuth的jwt和session回调在服务端完成AccessToken的过期检查与刷新,客户端仅保留用于API调用的AccessToken。以下是具体实现步骤:

1. 配置Credentials Provider,登录时获取并存储Token

在登录回调(authorize)中,调用后端登录接口后,从响应的Cookie中解析Refresh Token和AccessToken,将它们存入NextAuth的JWT(仅服务端可见),而非直接返回给客户端。

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import cookie from "cookie";
import jwt from "jsonwebtoken";

export default NextAuth({
  providers: [
    CredentialsProvider({
      credentials: {
        email: { label: "邮箱", type: "email" },
        password: { label: "密码", type: "password" }
      },
      async authorize(credentials, req) {
        // 调用后端登录接口
        const loginRes = await fetch(`${process.env.BACKEND_URL}/auth/login`, {
          method: "POST",
          body: JSON.stringify(credentials),
          headers: { "Content-Type": "application/json" },
          credentials: "include" // 允许携带Cookie(跨域场景需后端配置CORS)
        });

        const userData = await loginRes.json();
        if (!loginRes.ok) return null;

        // 从响应头解析后端设置的HttpOnly Cookie
        const cookieStr = loginRes.headers.get("Set-Cookie");
        const parsedCookies = cookie.parse(cookieStr || "");
        
        // 将用户信息、AccessToken、Refresh Token一起返回,传给后续的jwt回调
        return {
          ...userData,
          accessToken: parsedCookies.accessToken,
          refreshToken: parsedCookies.refreshToken
        };
      }
    })
  ],
  session: { strategy: "jwt" }, // 必须使用JWT策略,确保Token仅在服务端存储
  callbacks: {
    // 2. JWT回调:处理Token过期检查与刷新
    async jwt({ token, user }) {
      // 首次登录时,初始化JWT中的Token和过期时间
      if (user) {
        token.accessToken = user.accessToken;
        token.refreshToken = user.refreshToken;
        token.user = user;
        // 解析AccessToken的过期时间(转成毫秒)
        const decodedToken = jwt.decode(user.accessToken);
        token.expiresAt = decodedToken.exp * 1000;
        return token;
      }

      // 检查AccessToken是否即将过期(提前60秒刷新,避免请求失败)
      const now = Date.now();
      if (token.expiresAt && now < token.expiresAt - 60000) {
        return token; // 未过期,直接返回
      }

      // AccessToken过期,调用后端刷新接口
      try {
        const refreshRes = await fetch(`${process.env.BACKEND_URL}/auth/refresh`, {
          method: "POST",
          headers: {
            // 将存储在JWT中的Refresh Token传给后端验证
            "Cookie": `refreshToken=${token.refreshToken}`
          },
          credentials: "include"
        });

        const newTokens = await refreshRes.json();
        if (!refreshRes.ok) throw new Error("刷新Token失败");

        // 更新JWT中的AccessToken和过期时间
        token.accessToken = newTokens.accessToken;
        const newDecoded = jwt.decode(newTokens.accessToken);
        token.expiresAt = newDecoded.exp * 1000;
        
        // 如果后端返回新的Refresh Token,同步更新JWT中的值
        if (newTokens.refreshToken) {
          token.refreshToken = newTokens.refreshToken;
        }

        return token;
      } catch (err) {
        console.error("Token刷新失败:", err);
        // 刷新失败,清空Token,触发客户端重新登录
        return { ...token, accessToken: null, refreshToken: null, expiresAt: 0 };
      }
    },
    // 3. Session回调:仅返回客户端需要的信息,隐藏Refresh Token
    async session({ session, token }) {
      // 仅将用户信息和AccessToken传给客户端Session
      session.user = token.user;
      session.accessToken = token.accessToken;
      // 绝对不要将refreshToken、expiresAt等敏感字段返回给客户端
      return session;
    }
  }
});

关键细节说明

  • JWT策略必要性:只有使用JWT策略,才能把Refresh Token存储在服务端的JWT中,客户端无法直接访问,彻底避免安全风险。
  • 提前刷新Token:设置提前60秒刷新,避免客户端API请求因AccessToken刚好过期而失败。
  • 客户端API调用:直接从useSession获取accessToken,在请求头中携带(如Authorization: Bearer ${accessToken})即可。
  • 服务端路由验证:在getServerSideProps或middleware中调用getServerSession,通过返回的accessToken验证用户身份,无需依赖Refresh Token。
  • 后端配合:后端的刷新接口需要接收Refresh Token(通过Cookie或请求头),验证后返回新的AccessToken(及可选的新Refresh Token),同时保持Cookie的HttpOnly、Secure属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 01:39:51