Firebase Admin SDK生成的JWT缺失kid字段:如何添加或验证(含自定义声明)
问题分析
你用createCustomToken生成的是Firebase自定义登录令牌,这类令牌本身就不包含kid字段——它的定位是供客户端用来登录Firebase Auth、换取带kid的ID令牌,而非直接给第三方验证的凭证。你参考的官方文档里的验证逻辑是针对ID令牌的,不适用于自定义令牌。
解决方案
方案1:将自定义令牌交换为带kid的ID令牌(推荐)
通过Firebase Auth的登录接口,把自定义令牌转换成标准的ID令牌,这样生成的ID令牌会自动包含kid,同时完整保留你添加的自定义声明。在云函数中可以通过HTTP请求完成这个交换:
const admin = require('firebase-admin'); const axios = require('axios'); // 需要先安装axios依赖 admin.initializeApp(); exports.generateTokenWithKid = async (req, res) => { const uid = '目标用户UID'; const myAdditionalClaims = { role: 'admin', customData: '自定义内容' }; // 1. 生成自定义令牌 const customToken = await admin.auth().createCustomToken(uid, myAdditionalClaims); // 2. 调用Firebase Auth自定义令牌登录接口,换取带kid的ID令牌 const apiKey = '你的Firebase项目API_KEY'; // 从项目设置的「常规」标签页获取 const response = await axios.post( `Firebase Auth自定义令牌登录接口?key=${apiKey}`, { token: customToken, returnSecureToken: true } ); const idToken = response.data.idToken; // 此令牌符合官方验证标准,包含kid和自定义声明 res.json({ idToken }); };
交换后的ID令牌完全适配第三方的验证逻辑,直接用标准JWT库即可验证。
方案2:让第三方直接验证自定义令牌(无kid的情况)
如果第三方无法调整流程交换令牌,可以让他们按以下逻辑验证无kid的自定义令牌:
- 获取Firebase项目对应的服务账号公钥集合
- 遍历所有公钥,用RS256算法尝试验证令牌签名,直到找到匹配的公钥
- 额外验证以下核心声明:
iss必须是你的项目服务账号邮箱(格式:[项目ID]@appspot.gserviceaccount.com)aud必须固定为https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit- 检查
exp(过期时间)是否在有效期内,iat(签发时间)是否合理
注意:这种方法需要第三方遍历公钥,效率略低,且不符合Firebase的标准流程,仅作为临时替代方案。
补充说明
auth.currentUser.getIdToken()确实无法添加自定义声明,但通过方案1的交换流程,你既可以保留自定义声明,又能得到带kid的标准ID令牌,完美解决你的需求。
内容的提问来源于stack exchange,提问作者Witek
相关产品推荐
相关产品推荐

