Next.js 13.4 API路由中getServerSession无法获取完整用户数据
问题:Next.js 13.4 API路由中getServerSession获取的会话数据不完整
在Next.js 13.4项目中,已配置JWT和Session回调函数,但API路由通过getServerSession获取的用户数据仅包含name: undefined, email: 'test@test.com', image: undefined,而客户端页面用useSession()能正确获取完整用户信息。
相关代码及输出
[...nextauth]/route.js
import { connectToDB } from "@/app/server/db"; import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import bcrypt from 'bcrypt'; // Authorize function async function authorize(credentials) { const { email, password } = credentials; const { db } = await connectToDB("Tenants"); const user = await db.collection("Users").findOne({ email }); if (user) { const isPasswordValid = await bcrypt.compare(password, user.password); if (!isPasswordValid) { return null; } await db.collection("Users").updateOne({ email }, { $set: { lastLoggedIn: new Date() } }); return user } return null; } export const authOptions = NextAuth({ providers: [ CredentialsProvider({ authorize }) ], callbacks: { async jwt({ token, user }) { return { ...token, ...user }; }, async session({ session, token }) { session.user = token; return session; } }, session: { strategy: "jwt", }, pages: { signIn: '/login', }, secret: process.env.SECRET, NEXTAUTH_URL: process.env.NEXTAUTH_URL }); export { authOptions as GET, authOptions as POST };
用户对象
{ "_id": { "$oid": "615fb61796e77940b7f7a5e7" }, "email": "test@test.com", "password": "$2b$12$fCADz/THWfE7.hThRiFj2eNJxTL78.7zPtyRtERxkBlU2hwlYRJ9K", "firstName": "John", "lastName": "Smith", "lastLoggedIn": { "$date": "2023-07-21T17:36:06.893Z" }, "phoneNumber": "", "role": "Admin", "status": "Active", "company": "TestCompany", "jobTitle": "TestJobTitle", "department": "TestDepartment" }
API路由
import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/[...nextauth]/route" export async function GET(request) { const session = await getServerSession(authOptions); console.log(session) }
客户端页面控制台输出
user { "_id": "615fb61796e77940b7f7a5e7", "email": "test@test.com", "password": "$2b$12$fCADz/THWfE7.hThRiFj2eNJxTL78.7zPtyRtERxkBlU2hwlYRJ9K", "firstName": "John", "lastName": "Smith", "lastLoggedIn": "2023-07-21T17:36:06.893Z", "phoneNumber": "", "role": "Admin", "status": "Active", "company": "TestCompany", "jobTitle": "TestJobTitle", "department": "TestDepartment", "iat": 1689960966, "exp": 1692552966, "jti": "ae91e614-4fdb-4de4-9e5e-5b9879ca07ba" }
API路由控制台输出
{ user: { name: undefined, email: 'test@test.com', image: undefined } }
预期输出
{ user: { "_id": "615fb61796e77940b7f7a5e7", "email": "test@test.com", "firstName": "John", "lastName": "Smith", "lastLoggedIn": "2023-07-21T17:36:06.893Z", "phoneNumber": "", "role": "Admin", "status": "Active", "company": "TestCompany", "jobTitle": "TestJobTitle", "department": "TestDepartment" } }
原因分析
核心问题在于**authOptions的导出方式错误**:在[...nextauth]/route.js中,你将NextAuth(authOptions)的执行结果(路由处理函数)直接导出为authOptions,而非导出原始的配置对象。当API路由导入这个authOptions时,拿到的是路由处理函数而非NextAuth需要的配置结构,导致getServerSession无法触发自定义的jwt和session回调,只能返回默认的用户字段。
解决方案
修改[...nextauth]/route.js,将原始配置对象与路由处理函数分开导出:
import { connectToDB } from "@/app/server/db"; import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import bcrypt from 'bcrypt'; // Authorize function async function authorize(credentials) { const { email, password } = credentials; const { db } = await connectToDB("Tenants"); const user = await db.collection("Users").findOne({ email }); if (user) { const isPasswordValid = await bcrypt.compare(password, user.password); if (!isPasswordValid) { return null; } await db.collection("Users").updateOne({ email }, { $set: { lastLoggedIn: new Date() } }); // 移除敏感的password字段,避免存入JWT const { password, ...userWithoutPassword } = user; return userWithoutPassword; } return null; } // 单独导出原始配置对象 export const authOptions = { providers: [ CredentialsProvider({ authorize }) ], callbacks: { async jwt({ token, user }) { return { ...token, ...user }; }, async session({ session, token }) { session.user = token; return session; } }, session: { strategy: "jwt", }, pages: { signIn: '/login', }, secret: process.env.SECRET, NEXTAUTH_URL: process.env.NEXTAUTH_URL }; // 基于配置对象创建并导出路由处理函数 const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
额外优化
- 从返回的用户对象中移除
password字段,避免敏感哈希密码存入JWT,降低安全风险。 - 确保
process.env.SECRET和process.env.NEXTAUTH_URL环境变量已正确配置。
修改后,API路由导入的authOptions为正确的配置对象,getServerSession会正常执行回调函数,返回与客户端一致的完整会话数据。
内容的提问来源于stack exchange,提问作者Sharif
相关产品推荐
相关产品推荐

