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

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 }

修复方案

问题出在两个核心点:

  1. jwt回调未返回默认token:当没有user参数时(比如会话刷新场景),jwt回调没有返回token对象,导致NextAuth无法维护有效的JWT会话,最终session callback中token为undefined。
  2. 手动生成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:27:47