Firebase本地模拟器调用FCM推送时凭据认证失败报401错误
问题描述
在本地Firebase emulator环境测试推送通知功能,基于Cloud Functions直接调用推送方法时出现权限报错,复现流程如下:
- 下载项目admin密钥,操作参考截图:

- 配置
GOOGLE_APPLICATION_CREDENTIALS环境变量,执行命令:
➜ Desktop export GOOGLE_APPLICATION_CREDENTIALS=pearl-cef7c-4833cff1a093.json
- 执行
firebase emulators:start命令启动模拟器 - 通过webhook调用FCM发送方法:
admin.messaging().sendToTopic(topic, message); - 调用失败,返回权限相关报错:
Make sure the credential used to authenticate this SDK has the proper permissions.
切换使用Service Accounts认证时仍然出现完全相同的问题,无法定位admin key认证失败的根本原因,完整运行报错日志如下:
i functions: Beginning execution of "push" {"structuredData":true,"severity":"INFO","message":"Hello logs!"} i functions: Finished "push" in ~1s /Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/utils/error.js:44 var _this = _super.call(this, errorInfo.message) || this; ^ FirebaseMessagingError: 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> <HEAD> <TITLE>PROJECT_NOT_PERMITTED</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <H1>PROJECT_NOT_PERMITTED</H1> <H2>Error 401</H2> </BODY> </HTML> ". Status code: 401. at FirebaseMessagingError.FirebaseError [as constructor] (/Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/utils/error.js:44:28) at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/utils/error.js:90:28) at new FirebaseMessagingError (/Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/utils/error.js:279:16) at Object.createFirebaseError (/Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/messaging/messaging-errors-internal.js:57:12) at /Users/me/Desktop/pearl-mobile/cloud-functions/functions/node_modules/firebase-admin/lib/messaging/messaging-api-request-internal.js:79:51 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { 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' } Node.js v18.0.0
问题根因
报错返回PROJECT_NOT_PERMITTED 401状态码的核心原因有两点:
- Firebase本地模拟器不提供FCM推送的模拟能力,所有FCM调用请求都会直接转发到官方FCM生产服务器,不存在本地环境免鉴权的逻辑
- 当前使用的认证凭证没有对应Firebase项目的FCM调用权限,或者项目本身未开通Cloud Messaging服务
解决步骤
按以下顺序排查即可解决:
- 先确认对应Firebase项目已开通Cloud Messaging服务:进入Firebase控制台找到目标项目,在构建分类下打开Cloud Messaging页面,按引导完成服务开通,未开通该服务的项目调用FCM接口会直接返回当前的401错误。
- 检查服务账号权限:不要使用自定义权限的服务账号,优先选择项目默认的
App Engine default service account,如果是自建服务账号,需要给账号绑定Firebase Admin SDK Administrator Service Agent角色,该角色自带FCM消息发送的全部所需权限。 - 确认环境变量配置正确:执行
echo $GOOGLE_APPLICATION_CREDENTIALS校验输出的密钥文件路径,建议直接使用密钥文件的绝对路径配置环境变量,避免相对路径导致SDK加载到其他无权限的凭证。 - 检查SDK初始化逻辑:本地调试时Cloud Functions内的admin SDK直接用无参
admin.initializeApp()初始化即可,不要在初始化参数里硬编码其他无权限的凭证,SDK会自动读取系统环境变量里配置的密钥。
注意:本地调试FCM逻辑时发出的推送是真实生效的,会发送到对应主题/设备的正式用户,测试时请使用专用测试主题、测试设备token,避免干扰正式用户。
内容的提问来源于stack exchange,提问作者Zorayr
相关产品推荐
相关产品推荐

