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

Google OAuth登录后Supabase无法获取已登录用户问题

问题分析

这个问题的核心是OAuth重定向回调完成后,服务器端的Supabase Auth会话还未完全初始化,导致首次访问/complete_profile时getUser()无法获取用户,抛出missing sub claim错误。刷新页面后浏览器已携带完整的Auth Cookie,因此能正常获取用户。

另外你的代码里存在一个小错误:checkIfUserExists(await user?.id)中的await是多余的,user已经是await getUser()的结果,无需再次异步等待。


解决方案

方案1:改用客户端组件处理Auth状态(推荐)

客户端组件可以监听Supabase的Auth状态变化,确保会话完全初始化后再执行用户存在性检查和跳转逻辑,避免服务器组件首次渲染时的会话延迟问题。

步骤1:创建客户端组件CompleteProfileClient.js

'use client';

import { useEffect, useState } from 'react';
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
import { useRouter } from 'next/navigation';
import LeftColomn from "@/components/SignUp/LeftColomn/LeftColomn";
import RightColumnSeeker from "@/components/SignUp/RightColomnSeeker/RightColomnSeeker";

export default function CompleteProfileClient() {
  const [loading, setLoading] = useState(true);
  const router = useRouter();
  const supabase = createClientComponentClient();

  useEffect(() => {
    const checkAuthAndUser = async () => {
      // 监听Auth状态,确保会话就绪
      const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => {
        if (!session?.user) return;
        
        // 检查用户是否已存在于数据库
        const { data } = await supabase
          .from('Seekers')
          .select()
          .eq('unique_id', session.user.id)
          .single();

        if (data?.unique_id) {
          router.push('/all-jobs');
        } else {
          setLoading(false);
        }
        subscription.unsubscribe();
      });

      // 立即检查当前会话
      const { data: { user } } = await supabase.auth.getUser();
      if (user) {
        subscription.unsubscribe();
        const { data } = await supabase
          .from('Seekers')
          .select()
          .eq('unique_id', user.id)
          .single();
        if (data?.unique_id) {
          router.push('/all-jobs');
        } else {
          setLoading(false);
        }
      }
    };

    checkAuthAndUser();
  }, []);

  if (loading) {
    return <div>加载中...</div>;
  }

  return (
    <div className="flex h-screen">
      <LeftColomn />
      <RightColumnSeeker />
    </div>
  );
}

步骤2:修改原服务器组件CompleteProfile.js

import CompleteProfileClient from './CompleteProfileClient';

export default async function CompleteProfile() {
  return <CompleteProfileClient />;
}

方案2:服务器组件添加错误重定向逻辑

如果坚持使用服务器组件,可以在getUser()失败时重定向到当前页面,触发重新渲染以获取完整的Auth会话:

import LeftColomn from "@/components/SignUp/LeftColomn/LeftColomn";
import RightColumnSeeker from "@/components/SignUp/RightColomnSeeker/RightColomnSeeker";
import getUser from "@/lib/getUser/getUser";
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";

async function checkIfUserExists(id: string) {
    const supabase = createServerComponentClient({ cookies })
    const { data, error } = await supabase
        .from('Seekers')
        .select()
        .eq('unique_id', id)
        .single()

    if (error) { console.log(error); }
    return data;
}

export default async function CompleteProfile() {
    const user = await getUser();
    
    // 若获取用户失败,重定向刷新页面
    if (!user) {
        redirect('/complete_profile?refresh=' + Date.now());
    }

    const result = await checkIfUserExists(user.id);

    if (result?.unique_id) {
        redirect('/all-jobs')
    } else {
        return (
            <div className="flex h-screen">
                <LeftColomn />
                <RightColumnSeeker />
            </div>
        )
    }
}

额外注意事项

  1. 确保Supabase控制台的重定向URL已正确添加包含/complete_profile的完整地址(如http://localhost:3000/complete_profile和生产环境URL)。
  2. 移除getUser()函数中无意义的cookies().getAll()调用,避免不必要的性能开销。

内容的提问来源于stack exchange,提问作者Mohd Zaid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:28:17