Firebase FCM 401错误:send方法正常但sendToTopic调用失败
解决Firebase Admin SDK发送主题消息时的401 PROJECT_NOT_PERMITTED错误
问题描述
用Node.js搭建后端服务,调用admin.messaging().send()发送单设备消息完全正常,但调用sendToTopic发送主题消息时,出现401错误:
An error occurred when trying to authenticate to the FCM servers.
Make sure the credential used to authenticate this SDK has the proper permissions.
See https://firebase.google.com/docs/admin/setup for setup instructions.PROJECT_NOT_PERMITTED
Error 401
示例代码如下:
示例1(正常工作的单设备消息)
// Load the AWS SDK for Node.js var AWS = require("aws-sdk"); // Set the region AWS.config.update({ region: "ap-northeast-2" }); var admin = require("firebase-admin"); var serviceAccount = require("../firebadeCredentialInformation.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), }); module.exports.handler = async (event) => { console.log(event); var body = JSON.parse(event.body); console.log(body); var topic; var topicPayload; try { //body, title, data, token const message = { data: { type: "VOTE", senderName: body.senderName, question: body.question, questionRangeKey: body.questionRangeKey, senderToken: body.senderToken, gender: body.gender, schoolGrade: body.schoolGrade, schoolName: body.schoolName, }, token: body.token, }; //? Make sure the message is sent //TODO REMOVE BELOW AWAIT TO IMPROVE SPEED var result = await admin.messaging().send(message); console.log(result); return { statusCode: 200, body: JSON.stringify( { message: "Sucessfully sent response", input: event, }, null, 2 ), }; } catch (e) { console.log("Error", e); return { statusCode: 500, body: JSON.stringify( { message: e, input: event, }, null, 2 ), }; } };
示例2(报错的主题消息)
// Load the AWS SDK for Node.js var AWS = require("aws-sdk"); // Set the region AWS.config.update({ region: "ap-northeast-2" }); var admin = require("firebase-admin"); var serviceAccount = require("../firebadeCredentialInformation.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), }); module.exports.handler = async (event) => { console.log(event); var body = JSON.parse(event.body); console.log(body); var topic; var topicPayload; try { //body, title, data, token const message = { data: { type: "VOTE", senderName: body.senderName, question: body.question, questionRangeKey: body.questionRangeKey, senderToken: body.senderToken, gender: body.gender, schoolGrade: body.schoolGrade, schoolName: body.schoolName, }, token: body.token, }; //? Make sure the message is sent //TODO REMOVE BELOW AWAIT TO IMPROVE SPEED var result = await admin.messaging().send(message); console.log(result); if (body.schoolId != "") { //* Ff not missing school id const topicPayload = { data: { type: "TOPIC", senderName: body.senderName, question: body.question, questionRangeKey: body.questionRangeKey, senderToken: body.senderToken, gender: body.gender, schoolGrade: body.schoolGrade, schoolName: body.schoolName, }, }; const schoolId = body.schoolId; const topic = "/topics/" + schoolId; console.log(topic); //? Make sure the message is sent //TODO REMOVE BELOW AWAIT TO IMPROVE SPEED // Send a message to devices subscribed to the provided topic. var topicResult = await admin .messaging() .sendToTopic(topic, topicPayload); console.log(topicResult); } return { statusCode: 200, body: JSON.stringify( { message: "Sucessfully sent response", input: event, }, null, 2 ), }; } catch (e) { console.log("Error", e); return { statusCode: 500, body: JSON.stringify( { message: e, input: event, }, null, 2 ), }; } };
解决方案
1. 补充服务账号的主题消息权限
发送主题消息需要比单设备消息更宽泛的权限:
- 登录Firebase控制台,进入你的项目→项目设置→服务账号
- 找到你正在使用的服务账号(对应本地
firebadeCredentialInformation.json的账号) - 点击该账号的编辑角色按钮,添加
Firebase Cloud Messaging Admin角色(这个角色包含发送主题消息的所有必要权限) - 保存后等待5-10分钟让权限生效
2. 修正主题名格式
sendToTopic方法不需要手动添加/topics/前缀,SDK会自动处理。你的代码中手动拼接了前缀,会导致主题名格式错误,这也是触发权限验证失败的可能原因:
将:
const topic = "/topics/" + schoolId;
修改为:
const topic = schoolId;
如果客户端订阅的是/topics/xxx格式的主题,SDK会自动将传入的schoolId转换为正确的主题路径,无需手动添加前缀。
3. 重新下载服务账号密钥
如果权限配置正确但仍报错,可能是本地密钥文件过期或损坏:
- 回到Firebase控制台的服务账号页面,点击生成新的私钥,下载最新的JSON密钥文件
- 替换项目中的
firebadeCredentialInformation.json文件,重启服务后重试
内容的提问来源于stack exchange,提问作者Daniel Kang
相关产品推荐
相关产品推荐

