NextAuth.js登录后重定向前存储Cookie问题
核心问题原因
你当前在session回调中设置Cookie的方式存在两个关键问题:
js-cookie是纯客户端库,若session回调在服务端执行(比如SSR场景),完全无法操作浏览器Cookie;- 即使在客户端执行,登录后的重定向操作可能比Cookie设置的异步操作更快完成,导致Cookie还没写入就跳转了。
正确解决方案:在服务端回调中通过响应头设置Cookie
NextAuth的signIn回调在登录流程的服务端环节执行,此时可以直接通过res对象的响应头设置Cookie,确保在重定向到前端前,Cookie已经被浏览器接收。
修改后的完整代码
import NextAuth from 'next-auth'; import GoogleProvider from 'next-auth/providers/google'; import FacebookProvider from 'next-auth/providers/facebook'; import { serialize } from 'cookie'; // Next.js内置的Cookie序列化工具 export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID, clientSecret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET, authorization: { params: { scope: "profile email" } } }), FacebookProvider({ clientId: process.env.NEXT_PUBLIC_FACEBOOK_APP_ID, clientSecret: process.env.NEXT_PUBLIC_FACEBOOK_APP_SECRET, }), ], session: { jwt: true }, callbacks: { async signIn({ user, account, profile, req, res }) { try { const response = await fetch('url', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ first_name: profile.given_name, last_name: profile.family_name, email: profile.email, country_id: "13", ip: '127.0.0.1', platform: 'web', provider: account.provider, social_user_id: profile.sub, }), }); if (response.status === 200) { const data = await response.json(); const accessToken = data.response.data.token; user.accessToken = accessToken; user.profile = profile; // 服务端通过响应头设置Cookie const cookieOptions = { maxAge: 30 * 24 * 60 * 60, // 30天有效期 path: '/', // 全站可访问 secure: process.env.NODE_ENV === 'production', // 生产环境启用HTTPS安全Cookie sameSite: 'strict', // 严格同源策略,防止CSRF httpOnly: true, // 可选:若前端无需JS读取,开启后更安全(防XSS) }; // 序列化Cookie并写入响应头 res.setHeader('Set-Cookie', serialize('accessToken', accessToken, cookieOptions)); return true; } } catch (error) { console.error('Error signing in', error); return false; } }, async jwt({ token, user, account }) { if (user) { token.accessToken = user.accessToken; // 改用自己后端返回的token,而非第三方平台的accessToken token.user = user; } return token; }, async session({ session, token }) { session.accessToken = token.accessToken; session.user = token.user; // 此处无需再设置Cookie,已在signIn服务端环节完成 return session; }, async redirect() { return `/my-account`; }, }, });
关键细节说明
- 用内置工具序列化Cookie:使用Next.js自带的
cookie库的serialize方法,避免手动拼接Cookie字符串时出现格式错误; - 服务端设置响应头:在
signIn回调的服务端环境中,通过res.setHeader直接写入Set-Cookie响应头,确保浏览器在接收重定向响应前就完成Cookie存储; - 安全配置优化:
- 生产环境开启
secure,仅在HTTPS下传输Cookie; - 开启
sameSite: 'strict',防止跨站请求伪造; - 可选开启
httpOnly,禁止前端JS读取Cookie,大幅降低XSS攻击风险(若前端无需直接使用该token,建议开启);
- 生产环境开启
- 修正token来源:之前的
jwt回调错误使用了第三方平台的account.accessToken,现在改为使用自己后端返回的user.accessToken,符合业务需求。
验证方法
登录成功后,打开浏览器开发者工具的Application标签(Chrome),查看对应域名下的Cookies列表,确认accessToken是否存在;同时检查登录回调接口的响应头,确认包含Set-Cookie字段。
内容的提问来源于stack exchange,提问作者app tap
相关产品推荐
相关产品推荐

