Cloud Function(Node.js)中Firebase verifyIdToken验证失败问题
问题场景
部署在asia-east2区域、关联Firebase项目fatepal-e1b40的Node.js云函数中,调用admin.auth().verifyIdToken(idToken)持续失败,抛出Firebase ID token has invalid signature.错误,偶尔伴随auth/argument-error错误码。客户端已确认令牌结构合法,且通过最小化onRequest测试函数+Windows PowerShell传递有效令牌调用,问题仍复现。
测试函数代码
// functions/test-api/index.js const functions = require('firebase-functions/v1'); // 也尝试过v2导入 const admin = require('firebase-admin'); // admin 在主index.js中初始化 exports.testTokenVerification = functions .region('asia-east2') .https .onRequest(async (req, res) => { console.log(`[testTokenVerification] 函数触发. 请求方法: ${req.method}`); const authorizationHeader = req.headers.authorization || ''; const idToken = authorizationHeader.startsWith('Bearer ') ? authorizationHeader.split('Bearer ')[1] : null; console.log(`[testTokenVerification] Authorization头存在: ${!!authorizationHeader}`); console.log(`[testTokenVerification] 提取到令牌: ${idToken ? '已找到令牌' : '无令牌'}`); if (!idToken) { console.error('[testTokenVerification] 未传入Firebase ID Token.'); res.status(401).send('未授权:未提供令牌.'); return; } try { console.log('[testTokenVerification] 开始验证ID令牌...'); // 打印令牌首尾用于对比 console.log(`[testTokenVerification] 收到的令牌(长度 ${idToken.length}): ${idToken.substring(0, 10)}...${idToken.substring(idToken.length - 10)}`); const decodedToken = await admin.auth().verifyIdToken(idToken); const uid = decodedToken.uid; console.log(`[testTokenVerification] 令牌验证成功,对应UID: ${uid}`); res.status(200).json({ message: '令牌验证成功!', uid: uid }); } catch (error) { console.error('[testTokenVerification] 验证Firebase ID令牌出错:', error); res.status(403).send(`禁止访问: 函数内令牌验证失败 - ${error.code || error.message}`); } });
PowerShell调用方式
# 从Firebase Auth客户端SDK获取新鲜有效的ID令牌 $idTokenDirect = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNmO..." # 粘贴完整的已验证令牌 $headers = @{ "Authorization" = "Bearer " + $idTokenDirect } Invoke-WebRequest -Uri "https://asia-east2-fatepal-e1b40.cloudfunctions.net/testTokenVerification" -Method Get -Headers $headers -Verbose
排查与解决步骤
检查Admin SDK初始化正确性
确保主index.js中Admin SDK的初始化使用项目对应服务账号密钥,或借助Cloud Functions默认凭据时,云函数的服务账号已拥有Firebase Auth Admin权限。避免初始化时指定错误的项目ID或无效的服务账号配置。确认令牌与项目的关联匹配
将令牌复制到JWT解析工具中,检查aud(受众)字段是否为fatepal-e1b40,iss字段是否为https://securetoken.google.com/fatepal-e1b40。若令牌不属于当前项目,验证必然失败。排查令牌传输时的篡改/截断
对比云函数日志中打印的令牌首尾与客户端生成的令牌是否一致。PowerShell手动粘贴令牌时,若令牌含特殊字符(如换行、空格)可能导致传输异常,可改用文件读取方式避免格式错误:# 替代手动粘贴,从文件读取令牌 $idTokenDirect = Get-Content -Path "token.txt" -Raw | TrimEnd() $headers = @{ "Authorization" = "Bearer $idTokenDirect" } Invoke-WebRequest -Uri "https://asia-east2-fatepal-e1b40.cloudfunctions.net/testTokenVerification" -Method Get -Headers $headers -Verbose验证依赖版本兼容性
确保firebase-admin与firebase-functions版本匹配,避免版本不兼容导致的验证逻辑错误。尝试锁定兼容版本后重新部署:// package.json { "dependencies": { "firebase-admin": "^11.11.0", "firebase-functions": "^4.5.0" } }检查云函数网络访问权限
云函数需要访问Google公钥服务验证签名,若配置了VPC网络限制,需确保允许访问外部网络(或添加www.googleapis.com到VPC允许列表)。排查时间同步问题
ID Token有过期时间(exp字段),若云函数服务器系统时间与UTC时间偏差过大,可能误判令牌状态。可在函数中打印当前UTC时间,对比令牌exp时间确认:console.log(`当前UTC时间: ${new Date(Date.now()).toUTCString()}`);
内容的提问来源于stack exchange,提问作者Laisyyw Lai

