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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:05:15