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

Firebase Google重定向登录失败(弹窗登录正常)问题求助

Firebase Google重定向登录失败(弹窗登录正常)问题求助

大家好,我正在给我的Next.js Web应用集成Firebase认证,支持邮箱密码和Google登录两种方式。之前用Google弹窗登录(signInWithPopup)一切正常,但最近想改成**重定向登录(signInWithRedirect)**后,就遇到了问题,登录流程走不通,想请大家帮忙排查下问题~

下面是我的项目环境和核心代码:

环境版本

package.json中的Firebase依赖:

"firebase": "^11.10.0"

认证上下文核心代码(AuthContext.tsx)

'use client';
import { createContext, useEffect, useState, ReactNode, useContext } from 'react';
import { auth, provider } from '@/lib/firebase';
import {
  signOut,
  onAuthStateChanged,
  User,
  signInWithRedirect,
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  getRedirectResult,
  getIdToken,
  signInWithPopup,
} from 'firebase/auth';
import { toast } from '@/hooks/use-toast';
import { doc, getDoc, setDoc } from 'firebase/firestore';
import { db } from '@/lib/firebase';

interface AuthContextType {
  user: User | null;
  loading: boolean;
  login: () => Promise<void>;
  loginWithredirect: () => Promise<void>;
  loginWithEmailPwd: (email: string, password: string) => Promise<void>;
  signUpWithEmailPwd: (email: string, password: string) => Promise<void>;
  sendWelcomeEmail: (user: User) => Promise<void>;
  logout: () => Promise<void>;
}

const AuthContext = createContext<AuthContextType>({
  user: null,
  loading: true,
  login: async () => {},
  loginWithredirect: async () => {},
  loginWithEmailPwd: async () => {},
  signUpWithEmailPwd: async () => {},
  sendWelcomeEmail: async () => {},
  logout: async () => {},
});

export function useAuth() {
  return useContext(AuthContext);
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    console.log('loaded');
    getRedirectResult(auth)
      .then(async (result) => {
        console.log(result);
        if (result?.user) {
          console.log(result.user);
          await setToken(result.user);
          await saveUserToFirestore(result.user);
          setUser(result.user);
        }
      })
      .catch(() => {
        // Ignore errors, onAuthStateChanged will handle fallback
      });

    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setUser(user);
      setLoading(false);
    });

    return () => unsubscribe();
  }, []);

  // Google重定向登录
  const loginWithredirect = async () => {
    setLoading(true);
    try {
      await signInWithRedirect(auth, provider);
      // 原代码这里判断auth.currentUser是无效的,因为重定向后当前函数会终止,不会执行到这里
      if (auth.currentUser) {
        await setToken(auth.currentUser);
        await saveUserToFirestore(auth.currentUser);
      }
    } catch (e) {
      throw new Error('Login Failed! Try Again');
    } finally {
      setLoading(false);
    }
  };

  // Google弹窗登录(正常工作)
  const login = async () => {
    setLoading(true);
    try {
      const result = await signInWithPopup(auth, provider);
      if (result.user) {
        await setToken(result.user);
        await saveUserToFirestore(result.user);
        setUser(result.user);
      }
    } catch (e) {
      throw new Error('Login Failed! Try Again');
    } finally {
      setLoading(false);
    }
  };

  const setToken = async (user: User) => {
    const token = await getIdToken(user);
    document.cookie = `auth=${token}; path=/;`;
  };

  // 保存用户到Firestore
  const saveUserToFirestore = async (user: User) => {
    if (!user?.uid) return;
    const userRef = doc(db, 'users', user.uid);
    const snap = await getDoc(userRef);

    if (!snap.exists()) {
      try {
        console.log('trying brevo api...');
        sendWelcomeEmail(user);
        toast({
          title: 'Welcome email sent!',
          description: 'You have been added to our mailing list.',
        });
        await setDoc(userRef, {
          uid: user.uid,
          displayName: user.displayName || '',
          email: user.email || '',
          photoURL: user.photoURL || '',
          provider: user.providerData?.[0]?.providerId || 'google',
          createdAt: new Date(),
          welcomeEmailSent: true,
        });
      } catch (error) {
        toast({
          title: 'Failed to send welcome email',
          description: 'There was an error adding you to our mailing list.',
          variant: 'destructive',
        });
        await setDoc(userRef, {
          uid: user.uid,
          displayName: user.displayName || '',
          email: user.email || '',
          photoURL: user.photoURL || '',
          provider: user.providerData?.[0]?.providerId || 'google',
          createdAt: new Date(),
          welcomeEmailSent: false,
        });
      }
    } else {
      // 可选:更新用户元数据
      await setDoc(
        userRef,
        {
          displayName: user.displayName || '',
          email: user.email || '',
          photoURL: user.photoURL || '',
          provider: user.providerData?.[0]?.providerId || 'google',
          lastLogin: new Date(),
        },
        { merge: true }
      );
    }
  };

  // 邮箱密码登录
  const loginWithEmailPwd = async (email: string, password: string) => {
    setLoading(true);
    try {
      if (email && password) {
        await signInWithEmailAndPassword(auth, email, password);
      }
    } finally {
      setLoading(false);
    }
  };

  // 邮箱密码注册
  const signUpWithEmailPwd = async (email: string, password: string) => {
    setLoading(true);
    try {
      await createUserWithEmailAndPassword(auth, email, password);
      if (auth.currentUser) {
        await setToken(auth.currentUser);
        await saveUserToFirestore(auth.currentUser);
      }
    } finally {
      setLoading(false); // 原代码此处为setLoading(fals,已修正笔误)
    }
  };

  // 发送欢迎邮件(原代码未实现具体逻辑)
  const sendWelcomeEmail = async (user: User) => {
    // 此处应为调用Brevo API的逻辑
  };

  // 退出登录
  const logout = async () => {
    setLoading(true);
    try {
      await signOut(auth);
      document.cookie = 'auth=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;';
    } catch (e) {
      throw new Error('Logout Failed! Try Again');
    } finally {
      setLoading(false);
    }
  };

  return (
    <AuthContext.Provider
      value={{
        user,
        loading,
        login,
        loginWithredirect,
        loginWithEmailPwd,
        signUpWithEmailPwd,
        sendWelcomeEmail,
        logout,
      }}
    >
      {!loading && children}
    </AuthContext.Provider>
  );
}

具体问题现象

点击调用loginWithredirect后,页面正常跳转到Google登录页面,登录完成后也能跳回应用,但:

  1. 用户状态没有更新,页面依然显示未登录状态
  2. getRedirectResult返回的result始终是null
  3. 原本应该执行的saveUserToFirestore逻辑完全没触发

而弹窗登录的login函数完全正常,能正确获取用户信息、保存到Firestore并更新用户状态。

麻烦大家帮忙看看我的重定向登录逻辑哪里出了问题,或者有没有Firebase控制台的配置我漏掉了?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:19:29