Firebase函数间调用时ID Token的aud声明错误及验证问题
Firebase Cloud Functions 跨函数调用 Auth 验证问题排查与解决
问题1:functions.https.onCall 调用时 Audience 声明不匹配
原因
onCall 函数默认会验证 Firebase ID Token 的 aud(受众)字段为项目ID,但跨函数调用时,若直接用目标函数URL作为 targetAudience 生成Token,Token的aud会变成函数URL,导致验证失败。
解决步骤
调用方生成受众为项目ID的Token
调用方代码需指定targetAudience为项目ID,同时确保服务账号拥有生成ID Token的权限:const admin = require('firebase-admin'); admin.initializeApp(); async function invokeOnCallFunction() { const projectId = process.env.GCP_PROJECT; // 必须将targetAudience设为项目ID,匹配onCall的验证预期 const targetAudience = projectId; const idTokenClient = await admin.auth().getIdTokenClient(targetAudience); const idToken = await idTokenClient.idTokenProvider.fetchIdToken(targetAudience); // 构造onCall要求的请求体格式 const functionUrl = `https://${process.env.FUNCTION_REGION}-${projectId}.cloudfunctions.net/yourOnCallFunction`; const response = await fetch(functionUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${idToken}` }, body: JSON.stringify({ data: { /* 你的请求数据 */ } }) }); const result = await response.json(); console.log('调用结果:', result); }配置IAM权限
给调用方函数的默认服务账号(格式:{projectId}@appspot.gserviceaccount.com)添加 Service Account Token Creator 角色,该角色包含生成ID Token所需的serviceaccounts.signBlob权限,否则会返回401 Unauthorized。
问题2:切换到functions.https.onRequest后Token解码失败
原因
多数情况是Token提取错误:Authorization 请求头格式为 Bearer <token>,若直接传递完整头内容给 verifyIdToken,会因包含Bearer 前缀导致解码失败。
解决步骤
正确提取并验证Token
被调用方代码需先剥离Bearer前缀,再进行验证:const admin = require('firebase-admin'); admin.initializeApp(); exports.targetOnRequestFunction = functions.https.onRequest(async (req, res) => { const authHeader = req.headers.authorization; // 检查Authorization头格式 if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).send('缺少有效认证信息'); } // 提取纯Token字符串 const idToken = authHeader.split('Bearer ')[1]; try { const decodedToken = await admin.auth().verifyIdToken(idToken); // 可选:手动验证aud字段(根据调用方生成Token时的targetAudience选择) const validAudiences = [ process.env.GCP_PROJECT, `https://${process.env.FUNCTION_REGION}-${process.env.GCP_PROJECT}.cloudfunctions.net/targetOnRequestFunction` ]; if (!validAudiences.includes(decodedToken.aud)) { throw new Error('受众声明不合法'); } // 验证通过,处理业务逻辑 res.status(200).send({ success: true, uid: decodedToken.uid }); } catch (error) { console.error('Token验证失败:', error); res.status(403).send('无效的认证Token'); } });调用方传递Token的注意事项
调用方生成Token时,targetAudience可设为项目ID或函数URL,只需确保被调用方的validAudiences包含对应值即可。
内容的提问来源于stack exchange,提问作者Ryan Saunders
相关产品推荐
相关产品推荐

