You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Messaging v1发送推送报401 PROJECT_NOT_PERMITTED错误

问题背景

运行搭载Firebase Admin SDK的Node服务时,每次尝试从服务端发送推送通知都会返回401错误,获取到的完整错误信息如下:

errorInfo: {
  code: 'messaging/authentication-error',
  message: 'An error occurred when trying to authenticate to the FCM servers. Make sure the credential used to authenticate this SDK has the proper permissions. Raw server response: "<HTML>\n' +
    '<HEAD>\n' +
    '<TITLE>PROJECT_NOT_PERMITTED</TITLE>\n' +
    '</HEAD>\n' +
    '<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n' +
    '<H1>PROJECT_NOT_PERMITTED</H1>\n' +
    '<H2>Error 401</H2>\n' +
    '</BODY>\n' +
    '</HTML>\n' +
    '". Status code: 401.'
},
codePrefix: 'messaging'

已完成的排查操作

  • 已完成服务账号配置,下载了对应.json密钥文件
  • 已进入Google Cloud平台为服务账号添加了所有疑似必要的相关权限,服务账号权限配置如下:
    服务账号权限配置截图
  • 本地服务初始化代码如下:
const admin = require('firebase-admin');
const messaging = require('firebase-admin/messaging');
const serviceAccount = require('<path-to-key>');

const fbApp = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    projectId: '<PROJECT_ID>',
    databaseURL: '<DB_URL>'
});
  • 已查阅v1版本官方文档,未定位到缺失的权限项
  • 已确认本地通过firebase login登录了正确的Google账号,排除账号登录错误问题
  • 发送推送的业务代码如下:
const sendPushNotifications2 = async (topic, reminder) => {
    const payload = genPayload2(reminder);
    //await messaging.getMessaging(fbApp).sendToTopic(topic, payload);
    await admin.messaging(fbApp).sendToTopic(topic, payload);
};
  • 已校验密钥.json文件中的client_id、client_email、private_key_id字段值正确,但未找到private_key属性的校验入口,未完成该字段的正确性校验。

排查方案(按优先级从高到低验证)
  • 确认Firebase对应项目已正常开通Cloud Messaging服务
    进入Firebase控制台对应项目的消息推送页面,确认服务状态正常,不存在项目欠费、功能被限制的情况。返回PROJECT_NOT_PERMITTED错误的核心原因绝大多数是项目层面未开通FCM服务,和服务账号的细粒度权限无关。
  • 校验初始化代码中的项目ID与密钥所属项目完全匹配
    多项目并行时很容易出现密钥属于A项目、代码里手动填写的projectId属于B项目的问题,直接读取密钥文件内自带的project_id字段即可,不需要手动硬编码,修改初始化配置如下:
    const fbApp = admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        projectId: serviceAccount.project_id,
        databaseURL: '<DB_URL>'
    });
    
  • 重新生成服务账号密钥,排除私钥损坏问题
    不需要手动校验private_key字段的正确性,直接在Google Cloud控制台对应服务账号的密钥管理页,新建并下载一份全新的JSON格式密钥,替换本地旧文件即可。密钥复制、下载过程中出现的私钥截断、换行丢失都会直接导致鉴权失败。
  • 修正服务账号权限配置
    不需要零散添加疑似相关的权限,直接给对应服务账号绑定Firebase Admin SDK Administrator Service Agent系统角色,即可满足FCM推送的全部鉴权要求,零散配权很容易出现依赖权限漏配的问题。
  • 排查本地网络代理影响
    如果本地运行时开启了HTTPS代理,部分代理的流量解密功能会破坏请求的鉴权签名,导致Google侧校验失败返回401。可以临时关闭代理测试,或给Node进程配置NO_PROXY规则,让FCM相关请求不走代理。
  • 后续可升级API调用方式
    代码中使用的sendToTopic属于旧版API,v1版本SDK推荐使用send方法构造消息体发送,该问题不会触发401错误,可在鉴权问题修复后再调整。

内容的提问来源于stack exchange,提问作者Tlal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:36:30