如何在Firebase中创建并使用M2M令牌实现云函数间认证?
云函数A调用云函数B:获取服务账户访问令牌并验证
核心实现思路
在云函数环境中,无需手动管理服务账户密钥文件,可借助Google Auth Library自动获取默认服务账户的ID Token,用于调用受保护的云函数B。同时调整B的验证逻辑,仅允许指定服务账户的请求。
步骤1:为云函数A安装依赖
在云函数A的项目目录下执行:
npm install google-auth-library node-fetch
步骤2:云函数A中获取服务账户ID Token并调用B
const functions = require('firebase-functions'); const admin = require('firebase-admin'); const { GoogleAuth } = require('google-auth-library'); const fetch = require('node-fetch'); admin.initializeApp(); // 生成针对目标云函数的ID Token async function getServiceAccountIdToken(targetFunctionUrl) { const auth = new GoogleAuth(); const client = await auth.getIdTokenClient(targetFunctionUrl); return client.idTokenProvider.fetchIdToken(targetFunctionUrl); } exports.userBeforeCreate = functions.auth.user().beforeCreate(async (user) => { // 替换为你的云函数B的HTTPS端点 const functionBUrl = 'https://你的区域-你的项目ID.cloudfunctions.net/functionB'; try { // 获取服务账户ID Token const idToken = await getServiceAccountIdToken(functionBUrl); // 调用云函数B const response = await fetch(functionBUrl, { method: 'POST', // 根据B的实际请求方法调整 headers: { 'Authorization': `Bearer ${idToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ userData: user }) // 传递需要的参数 }); if (!response.ok) { throw new Error(`调用云函数B失败: ${await response.text()}`); } const result = await response.json(); // 处理B返回的结果 console.log('云函数B返回结果:', result); } catch (error) { console.error('处理请求时出错:', error); throw error; // 抛出错误以触发函数重试(可选) } });
步骤3:调整云函数B的验证逻辑,仅允许指定服务账户访问
修改B的代码,验证令牌的签发主体为你的项目默认服务账户:
const admin = require('firebase-admin'); const functions = require('firebase-functions'); admin.initializeApp(); exports.functionB = functions.https.onRequest(async (req, res) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(403).send('缺少有效授权令牌'); } const idToken = authHeader.split('Bearer ')[1]; try { const decodedToken = await admin.auth().verifyIdToken(idToken); // 替换为你的项目默认服务账户邮箱(格式:项目ID@appspot.gserviceaccount.com) const allowedServiceAccount = '你的项目ID@appspot.gserviceaccount.com'; // 验证令牌主体为允许的服务账户 if (decodedToken.sub === allowedServiceAccount) { // 验证通过,处理业务逻辑 res.status(200).json({ status: 'success', message: '请求已处理' }); } else { res.status(403).send('无权访问此端点'); } } catch (error) { console.error('令牌验证失败:', error); res.status(403).send('令牌无效或已过期'); } });
步骤4:配置权限,允许A的服务账户调用B
在Google Cloud Console中:
- 找到云函数B的详情页面
- 进入「权限」标签页
- 添加成员:输入你的项目默认服务账户邮箱(
项目ID@appspot.gserviceaccount.com) - 为其分配「Cloud Functions Invoker」角色
- 保存配置
内容的提问来源于stack exchange,提问作者Matt Whetton
相关产品推荐
相关产品推荐

