启用App Check的Firebase可调用函数返回"unauthenticated"错误求助
问题描述
调用Firebase Cloud Functions的uploadPhotoLimit函数时,客户端收到[firebase_functions/unauthenticated] UNAUTHENTICATED错误,Google Cloud日志提示"请求未被授权调用该服务"。已尝试为函数设置allAuthenticatedUsers权限、删除并重新部署函数,但问题仍未解决。因不想使用allUsers权限(会绕过App Check验证,降低安全性),寻求可行解决方案。
客户端代码
class FirebasePublicationRepository implements PublicationRepository { @override Future<String> publishPost({ required String postType, // "friends" ou "public" required String imagePath, required String title, required String description, }) async { final User? user = FirebaseAuth.instance.currentUser; if (user == null) { throw Exception("L'utilisateur n'est pas authentifié."); } final appCheckToken = await FirebaseAppCheck.instance.getToken(); if (appCheckToken == null) { throw Exception("App Check token is missing."); } try { final File file = File(imagePath); final bytes = await file.readAsBytes(); final String imageBase64 = base64Encode(bytes); final HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'europe-west1') .httpsCallable('uploadPhotoLimit'); final HttpsCallableResult result = await callable.call({ 'imageBase64': imageBase64, 'title': title, 'description': description, 'postType': postType, }); final data = result.data; if (data == null || data['postId'] == null) { throw Exception("Erreur de la Cloud Function : postId manquant."); } return data['postId'] as String; } catch (error) { throw Exception("Erreur lors de la publication du post: $error"); } } }
客户端报错日志
I/flutter ( 6354): Erreur lors de la publication du post: Exception: Erreur lors de la publication du post: [firebase_functions/unauthenticated] UNAUTHENTICATED I/flutter ( 6354): I/flutter ( 6354): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:652:7) I/flutter ( 6354): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:370:18) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #2 MethodChannelHttpsCallable.call (package:cloud_functions_platform_interface/src/method_channel/method_channel_https_callable.dart:22:24) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #3 HttpsCallable.call (package:cloud_functions/src/https_callable.dart:49:37) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #4 FirebasePublicationRepository.publishPost (package:coursios/blocs/publication/firebase_publication_repository.dart:46:42) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #5 PublicationBloc._onPublishPost (package:coursios/blocs/publication/publication_bloc.dart:49:22) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #6 Bloc.on.<anonymous closure>.handleEvent (package:bloc/src/bloc.dart:226:13) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): I/flutter ( 6354): #0 FirebasePublicationRepository.publishPost (package:coursios/blocs/publication/firebase_publication_repository.dart:60:7) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #1 PublicationBloc._onPublishPost (package:coursios/blocs/publication/publication_bloc.dart:49:22) I/flutter ( 6354): <asynchronous suspension> I/flutter ( 6354): #2 Bloc.on.<anonymous closure>.handleEvent (package:bloc/src/bloc.dart:226:13) I/flutter ( 6354): <asynchronous suspension>
Google Cloud日志提示
The request was not authorized to invoke this service. Additional troubleshooting documentation can be found at: [相关文档链接]
解决方案
1. 确认App Check与Cloud Functions的绑定配置
- 进入Firebase控制台,找到目标Cloud Function,检查是否已开启App Check保护。
- 验证App Check的提供者(如SafetyNet、App Attest)配置是否正确,确保客户端获取的token在有效期内且签名合法。
2. 修正权限配置细节
- 若使用第二代Cloud Functions(基于Cloud Run),需同时配置Cloud Run服务的权限:
- 打开Google Cloud控制台,找到函数对应的Cloud Run服务。
- 进入「权限」标签,为
allAuthenticatedUsers授予「Cloud Run Invoker」角色。
- 确认Cloud Functions本身的权限配置:为
allAuthenticatedUsers授予「Cloud Functions Invoker」角色,避免仅配置Cloud Run而遗漏函数层面的权限。
3. 确保客户端认证信息正确传递
- 虽然HttpsCallable默认会自动携带Auth和App Check信息,可手动显式传递App Check token排查问题:
final HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'europe-west1') .httpsCallable('uploadPhotoLimit', options: HttpsCallableOptions( headers: { 'X-Firebase-AppCheck': appCheckToken!, }, )); - 验证用户Auth token有效性:调用
user.getIdToken()确认能正常获取有效token,排除Auth状态异常导致的认证失败。
4. 检查函数内部的验证逻辑
- 若函数中有自定义的App Check/Auth验证代码,确认逻辑无错误:
排查是否存在token过期、签名验证失败等问题。const appCheck = require('firebase-admin').appCheck(); exports.uploadPhotoLimit = async (req, res) => { const appCheckToken = req.headers['x-firebase-appcheck']; if (!appCheckToken) { return res.status(401).send('Unauthorized'); } try { await appCheck.verifyToken(appCheckToken); } catch (err) { return res.status(401).send('Unauthorized'); } // 后续业务逻辑 };
5. 验证服务账号权限
- 确认Firebase App Check的服务账号拥有验证token的权限,避免因账号权限不足导致验证失败。
内容的提问来源于stack exchange,提问作者Mitsu
相关产品推荐
相关产品推荐

