使用Next-auth的callbacks选项遇问题:自定义Session返回null
解决Next-Auth自定义Session返回null的问题
问题根源
你的代码存在两个核心问题:
- authorize函数返回字段不全:仅返回了
id:1和name:user.name,缺少后续要用到的_id、username等字段,导致session回调中无法获取对应值。 - 未利用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
相关产品推荐
相关产品推荐

