Next.js 14 + Next-Auth出现Session cookie超4096字节错误求解决
问题描述
此前使用Next.js 13.x.x版本时Next-Auth认证功能正常,升级至Next.js 14.x.x后,终端控制台报错:Session cookie exceeds allowed 4096 bytes.,认证功能异常。
相关代码如下:
authOptions 完整代码
import { AuthOptions } from "next-auth"; import { PrismaAdapter } from "@next-auth/prisma-adapter"; import prisma from "./prisma"; import CredentialsProvider from "next-auth/providers/credentials"; import bcrypt from "bcrypt"; export const authOptions: AuthOptions = { adapter: PrismaAdapter(prisma), providers: [ CredentialsProvider({ credentials: { email: { label: 'email', type: 'text' }, password: { label: 'password', type: 'password' }, }, authorize: async (credential) => { if (!credential?.email || !credential?.password) { throw new Error("Invalid email or password"); } const user = await prisma.user.findUnique({ where: { email: credential.email }, include: { histories: true, resto: true, } }); if (!user || !user?.password) { throw new Error("Email does not match any user..."); } const isCorrect = await bcrypt.compare(credential.password, user.password) if (!isCorrect) { throw new Error("Password salah euy") } return { ...user, id: user.id.toString(), name: user.name, role: user.role, }; }, }) ], callbacks: { jwt: async ({ token, user, session, trigger }) => { if (trigger === 'update') { return { ...token, ...session.user } } if (user) { const userRelation = await prisma.user.findUnique({ where: { id: Number(user.id) }, include: { histories: true, resto: true, } }); if (!userRelation) { throw new Error("User not found"); } return { ...token, // id: user.id, ...userRelation }; } if (token.name !== null && token.name !== undefined) { await prisma.user.update({ where: { id: Number(token.id) }, data: { name: token.name } }); } return token; }, session: async ({ session, token, user }) => { const newSession = { ...session, user: { ...session.user, id: token.id, name: token.name, role: token.role, } } return newSession; }, }, pages: { signIn: '/', error: '/', }, debug: true, session: { strategy: "jwt" }, secret: "rahasia", }
route.ts 调用代码
import { authOptions } from '@/lib/auth'; import NextAuth from 'next-auth'; const handler = NextAuth(authOptions); export { handler as GET, handler as POST }
next-auth.d.ts 类型声明
import NextAuth from "next-auth"; declare module "next-auth" { interface Session { user: { id: string; name: string; email: string; role: string; [key: string]: string; }; } }
解决方案
不需要降级回Next.js 13,问题核心是JWT中存储了大量冗余数据,导致Cookie体积超过浏览器允许的4096字节限制。
1. 移除JWT中的冗余关联数据
你的代码在authorize方法和jwt回调中,都查询并存储了用户的histories和resto关联对象,但session回调只用到了id、name、role等基础字段,这些关联数据完全没必要放进JWT。
修改authorize方法
移除关联查询,只获取用户基础信息:
const user = await prisma.user.findUnique({ where: { email: credential.email }, // 删除include字段,不再查询histories和resto });
修改jwt回调的用户登录逻辑
不再重复查询关联数据,只合并必要字段到token:
if (user) { return { ...token, id: user.id.toString(), name: user.name, email: user.email, role: user.role }; }
2. 迁移JWT回调中的数据库操作
jwt回调里的用户名称更新逻辑,应该移到独立的API路由中处理,不要在JWT回调里执行数据库操作——这会增加回调执行时间,还可能导致token不必要的更新膨胀。
3. 验证修复效果
修改完成后,保持debug: true重新测试,终端不再出现Cookie超标的报错即为修复成功。如果问题仍存在,检查是否有其他冗余字段被意外加入JWT,确保只保留session所需的必要数据。
内容的提问来源于stack exchange,提问作者Terhebat Hokage
相关产品推荐
相关产品推荐

