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

Next.js + Next-Auth自定义Cookie保存及Refresh Token处理咨询

解决Next-Auth中自定义refresh_token的Cookie存储问题

核心问题点

你现在遇到的问题根源是:signIn回调里的fetch请求是服务端发起的,后端返回的Set-Cookie头只会作用于服务端的请求上下文,不会自动同步到浏览器,所以浏览器收不到这个refresh_token的Cookie设置。

正确处理方案

1. 手动转发Set-Cookie到浏览器

既然signIn回调在服务端运行,你可以从后端响应里提取Set-Cookie头,通过Next.js的res对象直接把这个Cookie设置给浏览器。这是实现HttpOnly Cookie的最优方式,完全符合你想要的安全要求——HttpOnly Cookie无法被前端JS读取,能有效降低泄露风险。

2. 别把refresh_token存进session

session里的数据会被序列化后传到客户端(哪怕是Next-Auth的HttpOnly session cookie,里面的token如果包含refresh_token,一旦session cookie被盗,refresh_token也会跟着泄露)。相比之下,单独的HttpOnly Cookie安全性高得多,没必要多此一举存进session。

修改后的代码示例

import NextAuth from "next-auth/next";
import GithubProvider from "next-auth/providers/github";
import { User, Account, Profile } from "next-auth";
import type { NextApiRequest, NextApiResponse } from "next"

async function auth(req: NextApiRequest, res: NextApiResponse) {
  return await NextAuth(req, res, {
    providers: [
      GithubProvider({
        clientId: process.env.GITHUB_CLIENT_ID || '',
        clientSecret: process.env.GITHUB_CLIENT_SECRET || '',
      }),
    ],
    callbacks: {
      async signIn(params: { user: User | undefined; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean } | undefined; credentials?: Record<string, any> | undefined }) {
        const { user, account, profile } = params;
        if (!account?.access_token) return false;

        try {
          const backendRes = await fetch('http://127.0.0.1:8080/login/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ token: account.access_token }),
          });
          
          if (backendRes.ok) {
            // 提取并保存access_token到account
            const test_access_token = backendRes.headers.get('authorization')?.split(' ')[1];
            if (test_access_token && account) {
              account.test_access_token = test_access_token;
            }

            // 把后端的Set-Cookie头转发给浏览器
            const setCookieHeader = backendRes.headers.get('Set-Cookie');
            if (setCookieHeader) {
              res.setHeader('Set-Cookie', setCookieHeader);
            }

            return true;
          }
        } catch (error) {
          console.error(error);
        }
        return false;
      },
      async jwt({ token, account, profile }) {
        if (account) {
          token.test_access_token = account.test_access_token;
          token.id = profile?.name;
        }
        return token;
      },
      async session({ session, token, user }) {
        if (token) {
          session.test_access_token = token.test_access_token;
          session.user.id = token.id;
        }
        return session;
      },
    }
  });
}

export { auth as GET, auth as POST };

额外注意事项

  • 跨域Cookie配置:如果你的后端和Next.js应用不在同一域名下,后端设置Cookie时必须配置正确的Domain、Path、SameSite属性(比如HTTPS环境下用SameSite=None; Secure),不然浏览器会拒绝保存这个Cookie。
  • 刷新access_token的逻辑:之后要刷新access_token时,直接在服务端API路由里发请求给后端就行,浏览器会自动带上这个HttpOnly的refresh_token Cookie(只要请求符合跨域规则)。
  • Next-Auth自身session:保留Next-Auth原本的session cookie逻辑,它负责管理用户的登录状态,你的自定义refresh_token Cookie专门用来和后端做token刷新交互,两者各司其职。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 05:25:32