使用NextAuth时auth.js v5的route.ts文件出现Session为Null的问题
Auth.js v5 API路由中无法获取Session(服务器组件正常)
问题描述
使用Auth.js v5时,API路由中调用auth()始终返回null,但相同的auth()函数在服务器组件中可正常获取session。需要通过session提取用户ID查询数据库,但API路由一直返回401未授权。
相关代码
route.ts
import { auth } from "@/auth"; import { db } from "@/lib/db"; import { NextRequest, NextResponse } from "next/server"; export async function GET(req: NextRequest) { try { const session = await auth(); console.log(session, "session"); if (!session) { return NextResponse.json({ user: null, message: 'Unauthorized' }, { status: 401 }); } const id = Number(session?.user?.id); const user = await db.user.findUnique({ where: { id } }); if (!user) { return NextResponse.json({ user: null, message: 'User not found' }, { status: 404 }); } const { password, ...userData } = user; return NextResponse.json({ user: userData, message: 'User found' }, { status: 200 }); } catch (error: any) { return NextResponse.json({ error: error.message, message: "Something went wrong!" }, { status: 500 }); } }
auth.ts
import { PrismaAdapter } from "@auth/prisma-adapter"; import { PrismaClient } from "@prisma/client"; import NextAuth from "next-auth"; import authConfig from "./auth.config"; const prisma = new PrismaClient() export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: PrismaAdapter(prisma), secret: process.env.AUTH_SECRET, session: { strategy: "jwt" }, callbacks: { async session({ session, token }) { if (!token) {return session;} if (session.user && token.sub) { session.user.id = token.sub;} return session; }, async jwt({ token, user }) { if (user) { token.id = user.id; } return token;}}, ...authConfig,})
auth.config.ts
import { NextAuthConfig } from "next-auth"; import Credentials from "next-auth/providers/credentials"; import { db } from "./lib/db"; import { LoginSchema } from "./schemas/user-schema"; import { hash } from "./utils/bcrypt"; export default { providers: [ Credentials({ credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" } }, async authorize(credentials) { const validateFields = LoginSchema.safeParse(credentials); if (!validateFields.success) { return null; } const { email, password } = validateFields.data; const isUser = await db.user.findUnique({ where: { email } }) if (!isUser) { return null; } if (hash(password) === isUser.password){ return isUser as any; } return null; } }) ], } satisfies NextAuthConfig
解决方案
1. API路由中必须传递Request对象给auth()
在Next.js API路由中,auth()需要显式接收请求对象才能读取session相关的cookie或header信息。修改route.ts中的调用:
// 原代码 const session = await auth(); // 修改后 const session = await auth(req); // 传入req参数
2. 修复Credentials提供者的密码验证逻辑
密码验证逻辑错误:数据库中存储的是哈希后的密码,不能直接将输入密码重新哈希后对比(每次哈希的盐值不同,结果不一致)。需使用bcrypt的验证方法替换:
// 原代码 if (hash(password) === isUser.password){ return isUser as any; } // 修改后(假设utils/bcrypt中有verify异步方法) import { verify } from "./utils/bcrypt"; // ... if (await verify(password, isUser.password)){ return isUser as any; }
注意:bcrypt的验证方法是异步的,必须添加await。
3. 额外检查项
- 确认
.env文件中的AUTH_SECRET配置正确,且与服务器组件使用的一致; - 检查session策略:当前使用
jwt策略,确保callbacks中的session和jwt逻辑已正确将用户ID注入session。
修改后的完整route.ts示例
import { auth } from "@/auth"; import { db } from "@/lib/db"; import { NextRequest, NextResponse } from "next/server"; export async function GET(req: NextRequest) { try { const session = await auth(req); // 传入req参数 console.log(session, "session"); if (!session) { return NextResponse.json({ user: null, message: 'Unauthorized' }, { status: 401 }); } const id = Number(session?.user?.id); const user = await db.user.findUnique({ where: { id } }); if (!user) { return NextResponse.json({ user: null, message: 'User not found' }, { status: 404 }); } const { password, ...userData } = user; return NextResponse.json({ user: userData, message: 'User found' }, { status: 200 }); } catch (error: any) { return NextResponse.json({ error: error.message, message: "Something went wrong!" }, { status: 500 }); } }
内容的提问来源于stack exchange,提问作者VENOM
相关产品推荐
相关产品推荐

