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

Firebase SignInWithRedirect登录后getRedirectResult返回null问题求助

Firebase SignInWithRedirect 重定向后getRedirectResult返回null问题

我在Firebase托管的应用中使用signInWithRedirect实现Google登录认证,用户成功登录后重定向回应用,但getRedirectResult始终返回null,导致应用无法识别已登录状态。signInWithPopup可以正常工作,但为了移动端兼容性必须使用重定向方式。

已尝试的排查步骤

  • 确认域名已添加到Firebase Auth授权列表
  • 检查firebase.js配置完全符合文档要求
  • 验证Firebase托管应用与项目配置已正确关联
  • 清除浏览器缓存、历史记录,手动添加域名至第三方Cookie白名单
  • 环境变量配置正确,敏感信息未暴露

项目文件结构

  • firebase.js(Firebase配置文件)
  • AuthContext.js(认证状态管理)
  • LoginForm/index.jsx(登录表单组件)

核心代码片段

firebase.js

// Import the functions you need from the SDKs
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getDatabase } from "firebase/database";

// Your web app's Firebase configuration using environment variables
const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

// Initialize Firebase services
export const auth = getAuth(app);
export const db = getFirestore(app); 
export const realtimeDb = getDatabase(app);

AuthContext.js

import React, { createContext, useContext, useState, useEffect } from "react";
import {
  onAuthStateChanged,
  GoogleAuthProvider,
  signOut,
  signInWithRedirect,
  getRedirectResult,
} from "firebase/auth";
import { auth } from "./firebase";

const AuthContext = createContext();

export const useAuth = () => useContext(AuthContext);

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);
  const [googleData, setGoogleData] = useState(null);
  const [signupComplete] = useState(false);
  const [loading, setLoading] = useState(true);

  const googleProvider = new GoogleAuthProvider();
  googleProvider.setCustomParameters({ prompt: "select_account" });

  const loginWithGoogle = async () => {
    signInWithRedirect(auth, googleProvider);
  };

  useEffect(() => {
    const handleRedirectResult = async () => {
      try {
        const result = await getRedirectResult(auth);
        console.log("Result is:", result);
        if (result) {
          const user = result.user;
          setCurrentUser(user);
          setGoogleData({
            fullName: user.displayName,
            email: user.email,
            uid: user.uid,
            photoURL: user.photoURL,
          });
          console.log("Redirect sign-in successful, user:", user);
        }
      } catch (error) {
        console.error("Error handling redirect result:", error);
      }
    };
    handleRedirectResult();
  }, []);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        setCurrentUser(user);
        setGoogleData({
          fullName: user.displayName,
          email: user.email,
          uid: user.uid,
          photoURL: user.photoURL,
        });
        console.log("User authenticated:", user);
      } else {
        setCurrentUser(null);
        setGoogleData(null);
      }
      setLoading(false);
    });
    return () => unsubscribe();
  }, []);

  const logout = async () => {
    try {
      await signOut(auth);
      setCurrentUser(null);
      setGoogleData(null);
    } catch (error) {
      console.error("Logout Error: ", error);
    }
  };

  const value = {
    currentUser,
    googleData,
    signupComplete,
    loginWithGoogle,
    logout,
    loading,
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
};

LoginForm/index.jsx

// 注:原代码与AuthContext.js重复,推测为粘贴错误,以下为标准登录UI示例
import React from "react";
import { useAuth } from "../AuthContext";

export const LoginForm = () => {
  const { loginWithGoogle, currentUser } = useAuth();

  return (
    <div className="login-container">
      {currentUser ? (
        <div>
          <p>已登录:{currentUser.email}</p>
        </div>
      ) : (
        <button onClick={loginWithGoogle}>使用Google登录</button>
      )}
    </div>
  );
};

流程说明

  1. 用户点击登录按钮,触发loginWithGoogle调用signInWithRedirect
  2. 用户跳转至Google登录页面完成认证
  3. 重定向回应用后,预期getRedirectResult获取用户信息并更新状态

问题核心

重定向返回后getRedirectResult返回null,但Google端认证已成功,应用无法识别登录状态。


可能的解决方案

1. 调整getRedirectResult调用时机

当前代码中getRedirectResult的useEffect依赖为空数组,可能在Firebase Auth初始化完成前执行。修改为合并到onAuthStateChanged逻辑中,确保Auth实例就绪:

useEffect(() => {
  const handleAuthState = async () => {
    // 优先获取重定向结果
    const result = await getRedirectResult(auth);
    if (result) {
      console.log("Redirect result found:", result.user);
    }
    // 监听Auth状态变化
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setCurrentUser(user);
      if (user) {
        setGoogleData({
          fullName: user.displayName,
          email: user.email,
          uid: user.uid,
          photoURL: user.photoURL,
        });
      } else {
        setGoogleData(null);
      }
      setLoading(false);
    });
    return unsubscribe;
  };
  handleAuthState();
}, []);

2. 配置Auth的Cookie跨域策略

针对HTTPS环境下的跨域Cookie限制,在firebase.js中添加Cookie配置:

export const auth = getAuth(app);
// 仅在HTTPS环境下生效,适配跨域重定向场景
auth.settings.cookieSameSite = "none";

3. 验证重定向URL一致性

  • 确认Firebase控制台中授权的重定向URL与应用实际返回的URL完全一致(包括协议、域名、路径)
  • 若使用自定义域名,确保已完成Firebase域名验证流程

4. 避免重复初始化Auth实例

检查项目中是否存在多次调用initializeApp的情况,确保整个应用仅初始化一次Firebase App和Auth实例。

5. 检查浏览器隐私设置

  • 确认浏览器未阻止第三方Cookie(Firebase Auth依赖Cookie维护会话)
  • 测试时可使用浏览器隐私模式排除本地缓存干扰

内容的提问来源于stack exchange,提问作者Terry Phillips

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:54:57