NextAuth v4中API路由内getSession始终返回null问题排查
问题:Next.js中调用getSession/unstable_getServerSession始终返回null
我正在Next.js应用中集成Stripe,尝试引导用户进入结账流程,但在/pages/api/subscribe.ts文件中获取会话信息时遇到问题。使用getSession或unstable_getServerSession都始终返回null,控制台打印显示请求的Cookies正常,用户已通过NextAuth的GitHub集成登录。以下是相关代码,请帮忙排查哪里操作有误?
subscribe.ts代码
import { NextApiRequest, NextApiResponse } from "next"; // import { unstable_getServerSession } from "next-auth/next"; import { getSession } from "next-auth/react"; import { stripe } from "services/stripe"; // import { authOptions } from "./auth/[...nextauth]"; export default async (req: NextApiRequest, res: NextApiResponse) => { if(req.method == 'POST') { console.log(req, res); const session = await getSession({ req }); console.log(req.cookies, session); // console.log(session); if(!session) return; const stripeCustomer = await stripe.customers.create({ email: session.user.email, }) const stripeCheckoutSession = await stripe.checkout.sessions.create({ customer: stripeCustomer.id, payment_method_types: ['card'], billing_address_collection: 'required', line_items: [ { price: 'price_1Kn2z8HXoO2e9eo5NaPFzRV1', quantity: 1 } ], mode: 'subscription', allow_promotion_codes: true, success_url: process.env.STRIPE_SUCCESS_URL, cancel_url: process.env.STRIPE_CANCEL_URL }); return res.status(200).json({ sessionId: stripeCheckoutSession.id }); } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method not allowed'); } }
[...nextauth].js代码
import { query as q } from 'faunadb'; import NextAuth from "next-auth"; import GithubProvider from "next-auth/providers/github"; import { Fauna } from "services/fauna"; export const authOptions = { providers: [ GithubProvider({ clientId: process.env.GITHUB_ID, clientSecret: process.env.GITHUB_SECRET, authorization: { params: { scope: 'read:user' } } }), ], callbacks: { async signIn({ user, account, profile }) { const { email } = user; try { await Fauna.query( q.If( q.Not( q.Exists( q.Match( q.Index('user_by_email'), q.Casefold(user.email) ) ) ), q.Create( q.Collection('users'), { data: { email } } ), q.Get( q.Match( q.Index('user_by_email'), q.Casefold(user.email) ) ) ) ); return true; } catch (error) { console.log(error); return false; } } } }; export default NextAuth(authOptions);
问题排查与解决
核心问题1:服务端API错误使用客户端getSession方法
你在subscribe.ts中导入的next-auth/react下的getSession是客户端专属方法,无法在服务端API路由中直接调用。服务端必须使用next-auth/next下的服务端会话获取方法。
核心问题2:未传入authOptions配置
服务端获取会话时,必须传入authOptions来验证Cookies中的会话信息,你之前注释了相关导入和调用,这是会话返回null的关键原因。
修复步骤:
- 修改
subscribe.ts的会话获取逻辑:
import { NextApiRequest, NextApiResponse } from "next"; import { unstable_getServerSession } from "next-auth/next"; // 改用服务端方法 import { stripe } from "services/stripe"; import { authOptions } from "./auth/[...nextauth]"; // 导入authOptions配置 export default async (req: NextApiRequest, res: NextApiResponse) => { if(req.method == 'POST') { // 传入req、res和authOptions获取会话 const session = await unstable_getServerSession(req, res, authOptions); console.log(req.cookies, session); if(!session) { return res.status(401).json({ error: "未授权访问" }); // 返回明确的未授权状态 } // 剩余Stripe逻辑保持不变 const stripeCustomer = await stripe.customers.create({ email: session.user.email, }) const stripeCheckoutSession = await stripe.checkout.sessions.create({ customer: stripeCustomer.id, payment_method_types: ['card'], billing_address_collection: 'required', line_items: [ { price: 'price_1Kn2z8HXoO2e9eo5NaPFzRV1', quantity: 1 } ], mode: 'subscription', allow_promotion_codes: true, success_url: process.env.STRIPE_SUCCESS_URL, cancel_url: process.env.STRIPE_CANCEL_URL }); return res.status(200).json({ sessionId: stripeCheckoutSession.id }); } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method not allowed'); } }
版本兼容性检查:
- 若使用NextAuth v4+,
unstable_getServerSession已稳定,可直接替换为getServerSession(导入路径不变)。 - 确认
authOptions的导入路径与你的文件结构匹配,避免路径错误。
- 若使用NextAuth v4+,
优化未授权处理:
原代码中if(!session) return;会导致请求无响应,改为返回401状态码,方便前端处理未授权场景。
内容的提问来源于stack exchange,提问作者Lucas Marthins
相关产品推荐
相关产品推荐

