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

如何在React+Firebase 9与Chrome扩展Manifest V3中实现Google登录?

在React + Firebase 9 + Manifest V3环境下实现Google登录(解决"bad client id"错误)

问题核心

你开发基于React和Firebase 9的Chrome扩展(Manifest V3)时,尝试通过chrome.identity实现Google登录,已完成Identity配置且能弹出登录窗口,但选择邮箱后触发OAuth2 request failed: Service responded with error: 'bad client id: {0}'错误。

错误原因分析

  1. Firebase凭证创建方式错误:你错误地将客户端ID作为GoogleAuthProvider.credential()的第一个参数,该方法的正确参数是Google ID Token,而非客户端ID。
  2. 客户端ID未在Firebase授权:Chrome扩展的OAuth客户端ID未添加到Firebase的授权列表,导致Firebase无法验证该来源的token。
  3. Chrome Identity API使用不当:chrome.identity.getAuthToken()获取的是Chrome生态的token,而非Firebase所需的Google ID Token。

解决方案步骤

1. 替换Chrome Identity API调用(获取正确的ID Token)

使用chrome.identity.launchWebAuthFlow()替代getAuthToken(),获取Firebase兼容的Google ID Token:

const getGoogleAuthCredential = () => {
  return new Promise((resolve, reject) => {
    if (typeof chrome !== 'undefined' && chrome.identity) {
      // 替换为你在Google Cloud Console中创建的Chrome扩展OAuth客户端ID
      const clientId = "你的扩展客户端ID.apps.googleusercontent.com";
      const scopes = "openid email profile";
      const redirectUri = chrome.identity.getRedirectURL();
      // 生成随机nonce防止重放攻击
      const nonce = Math.random().toString(36).substring(2, 15);

      chrome.identity.launchWebAuthFlow({
        url: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&response_type=id_token&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scopes)}&nonce=${nonce}`,
        interactive: true
      }, (responseUrl) => {
        if (chrome.runtime.lastError) {
          console.error(chrome.runtime.lastError);
          reject(chrome.runtime.lastError);
          return;
        }
        // 从回调URL中提取ID Token
        const urlParams = new URLSearchParams(responseUrl.split('#')[1]);
        const idToken = urlParams.get('id_token');
        
        if (!idToken) {
          reject(new Error('未能获取ID Token'));
          return;
        }
        
        const credential = GoogleAuthProvider.credential(idToken);
        resolve(credential);
      });
    } else {
      reject(new Error('需要在Chrome扩展环境中运行'));
    }
  });
};

2. 配置Firebase与Google Cloud授权

  • Google Cloud Console:确保你的Chrome扩展OAuth客户端ID已启用Google Identity API,并配置正确的重定向URI(即chrome.identity.getRedirectURL()返回的地址)。
  • Firebase控制台:进入「Authentication」→「登录方法」→「Google」,将Chrome扩展的OAuth客户端ID添加到「已授权的客户端ID」列表中。
  • Manifest.json配置:确保扩展的manifest包含正确的权限与OAuth配置:
{
  "manifest_version": 3,
  "permissions": ["identity"],
  "oauth2": {
    "client_id": "你的扩展客户端ID.apps.googleusercontent.com",
    "scopes": ["openid", "email", "profile"]
  }
}

3. 完整修正后的登录处理函数

import { GoogleAuthProvider, signInWithCredential, signInWithPopup } from 'firebase/auth';
import triggerMessage from '../../components/common/SnackBar';
import { auth } from '../../firebase/firebase-config';

const getGoogleAuthCredential = () => {
  return new Promise((resolve, reject) => {
    if (typeof chrome !== 'undefined' && chrome.identity) {
      const clientId = "你的扩展客户端ID.apps.googleusercontent.com";
      const scopes = "openid email profile";
      const redirectUri = chrome.identity.getRedirectURL();
      const nonce = Math.random().toString(36).substring(2, 15);

      chrome.identity.launchWebAuthFlow({
        url: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&response_type=id_token&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scopes)}&nonce=${nonce}`,
        interactive: true
      }, (responseUrl) => {
        if (chrome.runtime.lastError) {
          console.error(chrome.runtime.lastError);
          reject(chrome.runtime.lastError);
          return;
        }
        const urlParams = new URLSearchParams(responseUrl.split('#')[1]);
        const idToken = urlParams.get('id_token');
        
        if (!idToken) {
          reject(new Error('未能获取ID Token'));
          return;
        }
        
        const credential = GoogleAuthProvider.credential(idToken);
        resolve(credential);
      });
    } else {
      reject(new Error('需要在Chrome扩展环境中运行'));
    }
  });
};

export const googleAuthHandler = async () => {
  try {
    let credential;
    if (window.location.origin.includes("chrome-extension")) {
      credential = await getGoogleAuthCredential();
    } else {
      const provider = new GoogleAuthProvider();
      await signInWithPopup(auth, provider);
      return;
    }
    const result = await signInWithCredential(auth, credential);
    return result.user;
  } catch (error) {
    console.error(error);
    triggerMessage("Google登录失败,请重试。", "error")
    return null;
  }
};

关键注意事项

  • 生成nonce参数时需确保随机性,避免固定值导致安全风险。
  • 验证Google Cloud Console中,Chrome扩展的OAuth客户端ID的重定向URI与chrome.identity.getRedirectURL()一致。
  • 确保Firebase项目的Google登录方法已启用。

内容的提问来源于stack exchange,提问作者Pratik Tiwari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:35:28