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

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,导致验证失败。

解决步骤

  1. 调用方生成受众为项目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);
    }
    
  2. 配置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 前缀导致解码失败。

解决步骤

  1. 正确提取并验证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');
      }
    });
    
  2. 调用方传递Token的注意事项
    调用方生成Token时,targetAudience 可设为项目ID或函数URL,只需确保被调用方的validAudiences包含对应值即可。


内容的提问来源于stack exchange,提问作者Ryan Saunders

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:47:45