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

使用Next-auth的callbacks选项遇问题:自定义Session返回null

解决Next-Auth自定义Session返回null的问题

问题根源

你的代码存在两个核心问题:

  1. authorize函数返回字段不全:仅返回了id:1和name:user.name,缺少后续要用到的_id、username等字段,导致session回调中无法获取对应值。
  2. 未利用JWT回调传递用户数据:CredentialsProvider默认使用JWT管理session,session回调中的user参数并非直接来自MongoDB的原始用户数据,而是从JWT token解析而来,因此需要先通过jwt回调将用户信息存入token。

修正后的完整代码

import { MongoClient } from "mongodb";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcrypt";
import NextAuth from "next-auth/next";

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email", placeholder: "Email" },
        password: {
          label: "Password",
          type: "password",
          placeholder: "Password",
        },
      },
      async authorize(credentials, req) {
        try {
          const client = await MongoClient.connect(process.env.MONGO_URL, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
          });
          const db = client.db("test");
          const user = await db
            .collection("users")
            .findOne({ email: credentials.email });

          if (!user) throw new Error("User is not found!");

          const checkPassword = await bcrypt.compare(
            credentials.password,
            user.password
          );
          if (!checkPassword) throw new Error("Password is incorrect!");

          // 返回需要的用户字段,MongoDB的_id需转成字符串才能序列化到JWT
          return {
            id: user._id.toString(),
            name: user.name,
            username: user.username,
            email: user.email,
          };
        } catch (error) {
          throw new Error(error.message);
        }
      },
    }),
  ],
  // 显式声明session策略为JWT(CredentialsProvider默认值,写出来更清晰)
  session: {
    strategy: "jwt",
  },
  callbacks: {
    // 登录时将用户信息存入JWT token
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.username = user.username;
        token.name = user.name;
      }
      return token;
    },
    // 从token中取出信息组装自定义session
    async session({ session, token }) {
      if (token) {
        session.user.id = token.id;
        session.user.username = token.username;
        session.user.name = token.name;
      }
      return session;
    },
  },
};

const handler = NextAuth(authOptions);
export { handler as POST, handler as GET };

关键修正说明

  • 完善authorize返回值:将MongoDB用户的_id转为字符串(避免ObjectId无法序列化),同时返回username等需要的字段。
  • 添加jwt回调:登录时把用户信息写入JWT token,确保后续session回调能从token中读取到完整数据。
  • session回调依赖token:不再直接使用session回调的user参数,而是从token中提取数据组装自定义session,适配JWT模式的session管理逻辑。

客户端验证示例

使用useSession钩子即可获取包含自定义字段的session:

import { useSession } from "next-auth/react";

function UserProfile() {
  const { data: session } = useSession();
  if (session) {
    console.log(session.user); // 输出包含id、username、name的用户对象
  }
  return (
    <div>
      {session && <p>用户名:{session.user.username}</p>}
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:52:33