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

Firebase Google认证弹窗关闭后(auth/popup-closed-by-user)错误延迟问题

问题原因及解决思路

延迟触发的可能原因

  • Safari隐私机制限制:Safari对跨域弹窗的行为有更严格的隐私管控,关闭弹窗后,浏览器不会立即同步通知父页面的监听脚本,Firebase Auth的内部检测逻辑需要等待浏览器的隐私检查周期结束,才会触发错误回调。
  • Firebase Auth轮询策略:signInWithPopup内部采用轮询方式检测弹窗状态,在Safari环境下,默认的轮询间隔可能设置得较长(约7秒),导致关闭弹窗后需要等待下一次轮询才会发现弹窗已关闭。
  • 浏览器事件队列阻塞:Safari在处理弹窗关闭事件时,若页面存在其他耗时任务,会阻塞事件队列,导致错误回调无法立即执行。

解决办法

1. 手动监听弹窗关闭事件

放弃使用Firebase原生的signInWithPopup,手动创建弹窗并监听关闭事件,配合Firebase的认证逻辑完成流程,这样能在弹窗关闭时立即触发处理:

export function signInWithGoogle(callback) {
  const provider = new GoogleAuthProvider();
  const authDomain = "你的authDomain地址";
  // 构造Google认证跳转URL
  const authUrl = `https://${authDomain}/__/auth/handler?${provider.buildQueryParameters()}`;
  const popup = window.open(authUrl, 'google-signin', 'width=500,height=600');
  
  // 轮询检测弹窗状态
  const checkPopupInterval = setInterval(() => {
    if (popup.closed) {
      clearInterval(checkPopupInterval);
      // 手动触发关闭错误回调
      callback(new Error('auth/popup-closed-by-user'), null, false);
    }
  }, 100);

  // 监听弹窗返回的认证结果
  window.addEventListener('message', (event) => {
    if (event.origin === `https://${authDomain}`) {
      clearInterval(checkPopupInterval);
      popup.close();
      try {
        const result = JSON.parse(event.data);
        if (result.user) {
          const credential = GoogleAuthProvider.credentialFromResult(result);
          const { isNewUser } = getAdditionalUserInfo(result);
          callback(null, result.user, isNewUser);
        }
      } catch (err) {
        callback(err, null, false);
      }
    }
  }, { once: true });
}

注意:需要替换代码中的authDomain为你的Firebase项目认证域名,同时确保Firebase控制台已配置正确的跨域消息接收权限。

2. 切换到signInWithRedirect

如果弹窗场景的延迟无法接受,可以改用重定向认证方式,这种方式依赖浏览器跳转机制,不会有弹窗关闭的延迟问题:

export function signInWithGoogle(callback) {
  const provider = new GoogleAuthProvider();
  signInWithRedirect(auth, provider)
    .then(() => getRedirectResult(auth))
    .then((result) => {
      if (result) {
        const user = result.user;
        const { isNewUser } = getAdditionalUserInfo(result);
        callback(null, user, isNewUser);
      }
    })
    .catch((error) => {
      callback(error, null, false);
    });
}

3. 升级Firebase版本

检查Firebase Auth的最新版本,官方可能针对Safari的特性调整了轮询策略,修复了弹窗关闭延迟的问题。

4. 优化页面主线程

确保触发登录弹窗时,页面没有阻塞主线程的耗时任务(如大量同步DOM操作、同步网络请求),避免影响错误回调的执行时机。

内容的提问来源于stack exchange,提问作者Will Ullrich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:45:31