Next-Auth中Session回调无法获取Token问题求助
NextAuth + Prisma Adapter 会话回调中token为undefined的问题解决
问题描述
我使用NextAuth搭配Prisma Adapter管理认证流程,默认情况下session callback返回的session仅包含部分字段,常规做法是通过token callback将额外信息传递到session callback,再返回包含额外信息的目标session。但目前遇到的问题是:session callback中的token对象始终为undefined,无法向session添加额外信息。
问题代码
import NextAuth from "next-auth" import CredentialsProvider from "next-auth/providers/credentials" import bcrypt from "bcrypt" import { PrismaAdapter } from "@auth/prisma-adapter" import jwt from 'jsonwebtoken'; import prisma from "@/utils/prisma" export const authOptions = { adapter: PrismaAdapter(prisma), providers: [ CredentialsProvider({ name: "credentials", credentials: { email: { label: 'Email', type: 'text' }, password: { label: 'Password', type: 'password' } }, async authorize(credentials) { if (!credentials.email || !credentials.password) { return null } const user = await prisma.user.findUnique({ where: { email: credentials.email } }) if (!user) { return null } const passwordMatch = await bcrypt.compare(credentials.password, user.password) if (!passwordMatch) { return null } const payload = { user } const token = jwt.sign(payload, process.env.NEXTAUTH_SECRET, { expiresIn: '5h' }); console.log(payload); return { ...user, accessToken: token } } }), ], session: { strategy: "jwt", maxAge: 12 * 60 * 60 // 12 hours }, callbacks: { jwt: async ({ token, user }) => { console.log('1'); if (user) { console.log('2:', user); return { ...token, accessToken: user.accessToken } } }, session: async ({ session, user, token }) => { console.log('session last', session); console.log('user last', user); console.log('token last', token); return { ...session, user: { ...session.user, accessToken: token.accessToken } } }, }, secret: process.env.NEXTAUTH_SECRET, debug: process.env.NODE_ENV === "development" } const handler = NextAuth(authOptions) export { handler as GET, handler as POST }
修复方案
问题出在两个核心点:
- jwt回调未返回默认token:当没有user参数时(比如会话刷新场景),jwt回调没有返回token对象,导致NextAuth无法维护有效的JWT会话,最终session callback中token为undefined。
- 手动生成JWT干扰流程:NextAuth的JWT会话策略会自动生成和管理JWT,手动生成的token会破坏内置流程,无需额外生成。
修改后的代码
import NextAuth from "next-auth" import CredentialsProvider from "next-auth/providers/credentials" import bcrypt from "bcrypt" import { PrismaAdapter } from "@auth/prisma-adapter" import prisma from "@/utils/prisma" export const authOptions = { adapter: PrismaAdapter(prisma), providers: [ CredentialsProvider({ name: "credentials", credentials: { email: { label: 'Email', type: 'text' }, password: { label: 'Password', type: 'password' } }, async authorize(credentials) { if (!credentials.email || !credentials.password) { return null } const user = await prisma.user.findUnique({ where: { email: credentials.email } }) if (!user) { return null } const passwordMatch = await bcrypt.compare(credentials.password, user.password) if (!passwordMatch) { return null } // 移除手动生成JWT的代码,直接返回用户核心字段 return { id: user.id, email: user.email, name: user.name } } }), ], session: { strategy: "jwt", maxAge: 12 * 60 * 60 // 12 hours }, callbacks: { jwt: async ({ token, user }) => { // 确保始终返回token对象,无论是否有user if (user) { // 将需要的用户信息添加到token中 token.userId = user.id token.email = user.email } return token }, session: async ({ session, token }) => { // 从token中提取信息添加到session if (token) { session.user.id = token.userId session.user.email = token.email // 如果需要其他字段,在这里添加 } return session }, }, secret: process.env.NEXTAUTH_SECRET, debug: process.env.NODE_ENV === "development" } const handler = NextAuth(authOptions) export { handler as GET, handler as POST }
关键修改说明
- 移除手动JWT生成:删除authorize中手动生成JWT的逻辑,让NextAuth自动处理会话token。
- 修复jwt回调:确保在所有分支都返回token对象,当有user时将需要的字段合并到token,无user时直接返回原token。
- 调整session回调:从传入的token中提取字段,合并到session对象中返回,此时token不再是undefined。
内容的提问来源于stack exchange,提问作者Yazan Ali
相关产品推荐
相关产品推荐

