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

如何从OnCall云函数调用带Firebase Token的另一个OnCall函数?

问题描述

我需要保护我的Cloud Functions,不清楚如何在从一个函数调用另一个函数时传递正确的Firebase Token,也不知道如何生成有效的idToken。我提供了两个OnCall云函数(Prova和Prova2)的代码示例,客户端通过FirebaseFunction.instance.httpCallable()调用这些函数。

Prova函数代码:

const { logger, HttpsError } = require("firebase-functions/v2");
const { initializeApp } = require("firebase-admin/app");
const { onCall } = require("firebase-functions/v2/https");

initializeApp();

exports.Prova = onCall(async (data) => {
  try {
    // 检查用户是否已认证
    if (!data.auth) {
      throw new HttpsError("unauthenticated", "用户未认证");
    }
    const idToken = ??
    const callResponse = await fetch('https://us-central1-NAME_PROJECT.cloudfunctions.net/Prova2', {
        method: 'POST',
        headers: { 
          'Content-Type': 'application/json',
          Authorization: `Bearer ${idToken}` 
        },
        body: JSON.stringify({
            "data": {}
        })
    });

    return { success: true, message: "操作成功" };
  } catch (error) {
    logger.error("错误:", error.message);
    return { success: false, message: "内部错误", details: error.message };
  }
});

Prova2函数代码:

const { logger } = require("firebase-functions/v2");
const { initializeApp } = require("firebase-admin/app");
const { onCall } = require("firebase-functions/v2/https");

initializeApp();

exports.Prova2 = onCall(async (data) => {
   // 检查用户是否已认证
  if (!data.auth) {
    throw new HttpsError('unauthenticated', '用户未认证');
  }
  try {
    return{ message: '操作成功' };
  } catch (error) {
    logger.error(error.message);
    return{ message: '操作失败' };
  }
});

解决方案

1. 修正云函数的认证参数获取

Firebase V2的onCall函数接收的参数是context对象,用户的认证信息在context.auth中,而非data.auth。你的代码错误地将context当作data处理,这会导致认证检查失效,需先修正这一点。

2. 生成有效的ID Token

在云函数中,可通过Firebase Admin SDK的auth().createIdToken(uid)方法,为当前认证用户生成有效的ID Token,该Token可用于调用其他需要用户身份的OnCall函数。

3. 正确调用另一个云函数

调用时需在请求头中携带生成的ID Token,并严格按照OnCall函数的请求格式传递数据。


修正后的完整代码

Prova函数(调用方)

const { logger, HttpsError } = require("firebase-functions/v2");
const { initializeApp } = require("firebase-admin/app");
const { getAuth } = require("firebase-admin/auth");
const { onCall } = require("firebase-functions/v2/https");

initializeApp();
const auth = getAuth();

exports.Prova = onCall(async (context) => {
  try {
    // 检查用户是否已认证
    if (!context.auth) {
      throw new HttpsError("unauthenticated", "用户未认证");
    }

    // 获取当前用户UID并生成ID Token
    const uid = context.auth.uid;
    const idToken = await auth.createIdToken(uid);

    // 调用Prova2函数
    const callResponse = await fetch('https://us-central1-NAME_PROJECT.cloudfunctions.net/Prova2', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${idToken}`
      },
      body: JSON.stringify({
        "data": {} // 此处可传递给Prova2的业务参数
      })
    });

    // 解析Prova2的响应
    const responseData = await callResponse.json();
    if (!callResponse.ok) {
      throw new HttpsError(responseData.error.code, responseData.error.message);
    }

    return { success: true, message: "操作成功", prova2Response: responseData };
  } catch (error) {
    logger.error("错误:", error.message);
    return { success: false, message: "内部错误", details: error.message };
  }
});

Prova2函数(被调用方)

const { logger, HttpsError } = require("firebase-functions/v2");
const { initializeApp } = require("firebase-admin/app");
const { onCall } = require("firebase-functions/v2/https");

initializeApp();

exports.Prova2 = onCall(async (context) => {
  // 检查用户是否已认证
  if (!context.auth) {
    throw new HttpsError('unauthenticated', '用户未认证');
  }

  try {
    // 获取当前用户UID,执行业务逻辑
    const uid = context.auth.uid;
    logger.info(`用户 ${uid} 调用了Prova2函数`);
    
    return { message: '操作成功', userId: uid };
  } catch (error) {
    logger.error(error.message);
    throw new HttpsError('internal', '内部错误', error.message);
  }
});

关键说明

  • Admin SDK权限:云函数中初始化的Admin SDK拥有最高权限,用createIdToken生成的Token与客户端登录后获取的Token效力一致,可正常通过OnCall函数的认证检查。
  • 请求格式:调用OnCall函数时,必须将参数放在data字段中,请求头需包含Content-Type: application/json和携带Token的Authorization头。
  • 错误处理:调用后需检查响应状态,解析错误信息并抛出标准的HttpsError,确保客户端能正确接收错误提示。

内容的提问来源于stack exchange,提问作者Luciano d'Agostino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:44:55