如何使用Cloud Run和Swift验证Firebase ID Token?
问题分析与解决方案
核心问题排查
你遇到的「Firebase ID token has no 'kid' claim」错误,大概率是Token传递逻辑错误导致后端拿到了无效/空值的Token,其次可能是Firebase Admin SDK初始化或Token获取环节的问题。
1. 前端Token传递方式错误
你的前端代码将ID Token直接作为endpoint参数传递:
await web.webCall(endpoint: userIDToken)
这完全不符合接口调用逻辑——endpoint应该是后端接口的URL地址,而ID Token需要放在请求的Header(推荐)或请求体中传递,否则后端从req.body.idToken根本拿不到有效Token,自然会验证失败。
2. 前端默认传递空字符串风险
代码中用?? ""默认返回空字符串,如果getIDToken()获取失败,空字符串会被传给后端,空Token必然没有kid声明。
3. 后端可能未正确解析请求体
如果后端Express没有配置JSON解析中间件,req.body会是undefined,导致获取的Token无效。
分步修复方案
第一步:修正前端Token传递逻辑
将ID Token放在HTTP请求头(推荐用Authorization: Bearer <token>)或请求体中,同时处理Token获取失败的情况:
// 确保成功获取到Token再发送请求 guard let userIDToken = try await signIn.result?.user.getIDToken() else { print("Failed to retrieve ID Token") return } // 构建请求示例(用Authorization头传递) guard let apiURL = URL(string: "https://your-cloud-run-service.com/api/verify-token") else { print("Invalid API URL") return } var request = URLRequest(url: apiURL) request.httpMethod = "POST" // 用Bearer Token格式放在Header request.setValue("Bearer \(userIDToken)", forHTTPHeaderField: "Authorization") // 发送请求(根据你的webCall方法调整参数) await web.webCall(request: request)
第二步:修正后端Token验证逻辑
场景1:从Authorization头获取Token
// 先确保Express配置了JSON解析中间件(如果用请求体传的话需要) app.use(express.json()); app.post('/api/verify-token', async (req, res) => { // 从Authorization头提取Token,去掉Bearer前缀 const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).send("No valid ID token provided"); } const idToken = authHeader.split(' ')[1]; try { const decodedToken = await admin.auth().verifyIdToken(idToken); const uid = decodedToken.uid; console.log("Verified user UID:", uid); res.status(200).json({ uid: uid }); } catch (error) { console.error("Token verification failed:", error); res.status(401).send("Invalid ID token"); } });
场景2:从请求体获取Token(如果前端用body传递)
确保前端请求体是JSON格式,且后端已配置express.json()中间件:
app.post('/api/verify-token', async (req, res) => { const idToken = req.body.idToken; if (!idToken) { return res.status(401).send("No ID token provided"); } try { const decodedToken = await admin.auth().verifyIdToken(idToken); const uid = decodedToken.uid; console.log("Verified user UID:", uid); res.status(200).json({ uid: uid }); } catch (error) { console.error("Token verification failed:", error); res.status(401).send("Invalid ID token"); } });
第三步:确认Firebase Admin SDK初始化正确性
在Cloud Run上可以直接使用默认应用凭据初始化,无需手动上传服务账号密钥:
const admin = require('firebase-admin'); // 自动使用Cloud Run的默认服务账号权限 admin.initializeApp();
如果手动初始化,需确保服务账号密钥正确,且账号拥有Firebase Auth Token Verifier权限。
内容的提问来源于stack exchange,提问作者Joe Alvini
相关产品推荐
相关产品推荐

