使用unstable_getServerSession保护NextAuth API时Session为null
NextAuth API路由无法获取Session问题排查与解决
登录状态下,pages/dashboard/index.js的getServerSideProps能正常获取Session,但调用/api/profile接口时,unstable_getServerSession返回null,导致接口返回401,Dashboard无法展示内容。已按照官方文档配置API路由权限,但未生效。
相关代码
pages/api/profile.js
import prisma from "../../../lib/prisma"; import { unstable_getServerSession } from "next-auth/next"; import { authOptions } from "../auth/[...nextauth]"; export default async function handler(req, res) { const session = await unstable_getServerSession(req, res, authOptions); console.log("SESSION", session); // 此处打印"null" if (!session) { return res.status(401).json("Not authorized"); } try { const user = await prisma.user.findUnique({ where: { email: session.user.email }, }); return res.status(200).json(user); } catch (error) { console.error(error); return res .status(503) .json( "Our server is not able to process the request at the moment, please try again later!" ); } }
pages/api/auth/[...nextauth].js
import NextAuth from "next-auth"; import CognitoProvider from "next-auth/providers/cognito"; import prisma from "../../../lib/prisma"; export const authOptions = { providers: [ CognitoProvider({ clientId: process.env.CLIENTID_NEXTAUTH, issuer: process.env.COGNITO_ISSUER, clientSecret: process.env.CLIENTSECRET_NEXTAUTH, }), ], session: { strategy: "jwt", maxAge: 30 * 24 * 60 * 60, updateAge: 24 * 60 * 60, }, callbacks: { async jwt({ token, account }) { if (account) { token.accessToken = account.access_token; } return token; }, async session({ session, token }) { const user = await prisma.user.findUnique({ where: { email: session?.user?.email }, }); if (!user) throw new Error("User not found in the database."); const mySession = { ...session, accessToken: token.accessToken, email: user.email, }; return mySession; }, }, }; export default NextAuth(authOptions);
pages/dashboard/index.js
import axios from "axios"; import React, { useState } from "react"; import { getSession, useSession } from "next-auth/react"; const Dashboard = (props) => { let { data: session, status } = useSession(); if (status === "loading") { return <p>Loading...</p>; } if (status === "unauthenticated") { window.location.reload(); } return ( <p> {props.userInfo.name} </p> ); }; export default Dashboard; export async function getServerSideProps(context) { const session = await getSession(context); if (!session) { return { redirect: { destination: "/", permanent: false, }, }; } console.log("SESSION IN INDEX", session); // 此处能正常打印Session const userInfo = await axios.get( `${process.env.BASE_URL}/api/profile?email=${session.email}` ); return { props: { session, userInfo: userInfo.data ? userInfo.data : null, }, }; }
问题原因与解决方案
核心原因
- API请求未携带Session凭证:
getServerSideProps中用axios调用/api/profile时,默认不会自动携带NextAuth的Session Cookie,导致API路由无法识别用户身份。 - Session回调逻辑缺陷:
session回调依赖session.user.email,若该值为空会触发查询失败;同时自定义Session结构时未保留标准user字段,可能导致Session解析异常。
修复步骤
1. 给API请求手动传递Cookie
修改getServerSideProps中的axios请求,从context中获取Cookie并携带:
export async function getServerSideProps(context) { const session = await getSession(context); if (!session) { return { redirect: { destination: "/", permanent: false, }, }; } console.log("SESSION IN INDEX", session); // 携带请求Cookie,让API路由识别Session const userInfo = await axios.get(`${process.env.BASE_URL}/api/profile`, { headers: { Cookie: context.req.headers.cookie || "" } }); return { props: { session, userInfo: userInfo.data ? userInfo.data : null, }, }; }
2. 优化Session回调逻辑
确保从token中获取可靠的用户标识,同时保留标准Session结构:
// pages/api/auth/[...nextauth].js callbacks: { async jwt({ token, account, user }) { // 首次登录时保存用户邮箱到token if (user) { token.email = user.email; } if (account) { token.accessToken = account.access_token; } return token; }, async session({ session, token }) { // 从token获取邮箱,避免依赖session.user.email const user = await prisma.user.findUnique({ where: { email: token.email }, }); if (!user) throw new Error("User not found in the database."); // 保留标准session.user结构,避免解析异常 return { ...session, accessToken: token.accessToken, user: { ...session.user, email: user.email, name: user.name } }; }, },
3. 额外检查项
- 确认环境变量
NEXTAUTH_URL已正确配置(生产环境需匹配域名),NextAuth依赖该值生成正确的Cookie。 - 检查浏览器DevTools的Application标签,确认存在
next-auth.session-tokenCookie,且域名与当前站点匹配。 - 验证Cognito的
issuer格式是否正确,应为https://cognito-idp.<region>.amazonaws.com/<userPoolId>。
内容的提问来源于stack exchange,提问作者ranran212
相关产品推荐
相关产品推荐

