Chrome扩展Manifest V3中Firebase signInWithCredential认证报错求助
解决Chrome扩展Manifest V3中Firebase认证的
auth/invalid-credential错误 问题原因
你遇到的id token is not issued by Google错误,核心是混淆了两种令牌:Firebase的getIdToken()返回的是Firebase自定义ID令牌,而非Google OAuth原生的id_token。而GoogleAuthProvider.credential(idToken)方法仅接受Google OAuth流程直接生成的令牌,因此会判定凭证无效。
解决方案
结合你需要支持Google OAuth和邮箱/密码用户的需求,以下两种方案可解决问题,其中方案1为通用所有用户类型的最优解:
方案1:使用Firebase自定义令牌(Custom Token)实现跨端认证
自定义令牌由Firebase Admin SDK生成,支持所有用户类型(Google OAuth、邮箱密码、匿名等),是最通用的跨端认证方案。
步骤:
后端生成自定义令牌
必须在Web应用后端(前端无法安全持有Admin SDK私钥)生成自定义令牌:// 后端Node.js示例 const admin = require('firebase-admin'); // 初始化Admin SDK(需配置服务账号密钥) admin.initializeApp({ credential: admin.credential.cert(serviceAccount) }); // 传入用户UID生成自定义令牌 admin.auth().createCustomToken(userUid) .then((customToken) => { // 将customToken返回给Web应用前端 res.json({ customToken }); }) .catch((error) => { console.error('生成自定义令牌失败:', error); res.status(500).send('生成令牌出错'); });Web应用传递令牌到扩展
Web应用获取后端返回的自定义令牌后,通过chrome.runtime.sendMessage发送给扩展:// Web应用前端代码 fetch('/api/generate-custom-token', { method: 'POST', body: JSON.stringify({ uid: auth.currentUser.uid }) }) .then(res => res.json()) .then(data => { // 发送令牌到扩展(替换为你的扩展ID) chrome.runtime.sendMessage('YOUR_EXTENSION_ID', { type: 'CUSTOM_TOKEN', token: data.customToken }); });扩展后台脚本完成认证
扩展的Service Worker中使用signInWithCustomToken登录:// 扩展后台脚本(Service Worker) import { getAuth, signInWithCustomToken } from "firebase/auth"; const auth = getAuth(); // 监听Web应用的消息 chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => { if (message.type === 'CUSTOM_TOKEN') { signInWithCustomToken(auth, message.token) .then(userCredential => { console.log('认证成功:', userCredential.user); sendResponse({ success: true }); }) .catch(error => { console.error('认证失败:', error); sendResponse({ success: false, error: error.code }); }); return true; // 保持消息通道等待异步响应 } });
方案2:针对Google OAuth用户传递原生Google id_token
如果仅需处理Google OAuth用户,可以直接传递Google原生的id_token:
步骤:
Web应用获取Google原生id_token
在Google OAuth登录流程中,从userCredential提取原生令牌:// Web应用Google登录代码 import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, new GoogleAuthProvider()) .then(result => { // 获取Google原生id_token const credential = GoogleAuthProvider.credentialFromResult(result); const googleIdToken = credential.idToken; // 发送到扩展 chrome.runtime.sendMessage('YOUR_EXTENSION_ID', { type: 'GOOGLE_ID_TOKEN', token: googleIdToken }); }) .catch(error => { console.error('登录失败:', error); });扩展后台脚本完成认证
扩展中使用Google原生令牌创建凭证并登录:// 扩展后台脚本 import { getAuth, signInWithCredential, GoogleAuthProvider } from "firebase/auth"; const auth = getAuth(); chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => { if (message.type === 'GOOGLE_ID_TOKEN') { const credential = GoogleAuthProvider.credential(message.token); signInWithCredential(auth, credential) .then(userCredential => { console.log('Google用户认证成功:', userCredential.user); sendResponse({ success: true }); }) .catch(error => { console.error('认证失败:', error); sendResponse({ success: false, error: error.code }); }); return true; } });
关键配置检查
- 确保Web应用和扩展使用完全相同的Firebase配置(apiKey、authDomain等);
- 在扩展的
manifest.json中配置externally_connectable,允许你的Web应用域名发送消息:"externally_connectable": { "matches": ["https://your-web-app-domain.com/*"] }
内容的提问来源于stack exchange,提问作者Francesco
相关产品推荐
相关产品推荐

