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

NextAuth谷歌登录后Session返回空对象问题求助

NextAuth Google登录跳转与Session为空问题解决

问题原因拆解

1. 返回URL时Session为空的原因

当你在signIn回调中直接返回URL字符串时,NextAuth会跳过后续的会话持久化流程——它只执行跳转操作,不会触发jwt和session回调来生成并存储用户会话。这就导致后续session回调里拿不到用户数据,自然返回的user对象为空。

2. 返回true时跳回登录页的原因

返回true后,NextAuth会正常完成会话创建流程(生成jwt、同步session),但默认会跳转到你配置的callbackUrl(如果没手动配置,默认是发起登录请求的页面,通常是登录页),所以才会出现Session正常但跳回登录页的情况。

正确实现方案

核心思路是:先让NextAuth完成会话创建(signIn回调返回true),把用户是否存在的状态存入会话,再通过登录回调页或Middleware来完成跳转。

步骤1:配置NextAuth回调,存储用户状态

修改[...nextauth].js文件,在signIn回调中调用后端接口判断用户,将结果存入token和session:

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  callbacks: {
    async signIn({ user }) {
      // 调用后端接口检查用户是否存在
      const checkRes = await fetch(`${process.env.NEXT_PUBLIC_API_BASE}/check-user`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: user.email }),
      });
      const { exists } = await checkRes.json();

      // 将用户存在状态附加到user对象,供jwt回调使用
      user.exists = exists;
      // 返回true,让NextAuth完成会话创建流程
      return true;
    },
    async jwt({ token, user }) {
      // 首次登录时,将用户信息存入token
      if (user) {
        token.email = user.email;
        token.exists = user.exists;
      }
      return token;
    },
    async session({ session, token }) {
      // 将token中的信息同步到session,供前端使用
      session.user.email = token.email;
      session.user.exists = token.exists;
      return session;
    },
  },
  // 指定登录成功后的默认回调页,后续在这里处理跳转
  callbackUrl: "/auth/callback",
});

步骤2:创建登录回调页处理跳转

在pages/auth/callback.js中,根据session中的用户状态完成跳转:

import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { useRouter } from "next/router";

export default function AuthCallback() {
  const { data: session, status } = useSession();
  const router = useRouter();

  useEffect(() => {
    // 会话验证完成后,根据用户存在状态跳转
    if (status === "authenticated") {
      router.push(session.user.exists ? "/" : "/apply-form");
    }
  }, [status, session, router]);

  return <div>登录验证中...</div>;
}

可选:用Middleware实现无UI跳转(Next.js 12+)

如果不想显示中间跳转页,可以用Next.js Middleware直接处理:

创建middleware.js文件:

import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";

export async function middleware(req) {
  const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
  const currentPath = req.nextUrl.pathname;

  // 仅在登录回调页触发跳转逻辑
  if (currentPath === "/auth/callback" && token) {
    return NextResponse.redirect(
      new URL(token.exists ? "/" : "/apply-form", req.url)
    );
  }

  return NextResponse.next();
}

// 指定匹配的路由
export const config = {
  matcher: ["/auth/callback"],
};

内容的提问来源于stack exchange,提问作者Sb Zakaria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:45:29