Flutter调用Firebase可调用云函数遇权限拒绝问题求助
Flutter调用Firebase可调用云函数遭遇权限拒绝问题
错误日志
W/FirebaseContextProvider( 3655): Error getting App Check token. Error: com.google.firebase.FirebaseException: Error returned from API. code: 403 body: App attestation failed. D/TrafficStats( 3655): tagSocket(294) with statsTag=0xffffffff, statsUid=-1 E/flutter ( 3655): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [firebase_functions/permission-denied] PERMISSION_DENIED E/flutter ( 3655): E/flutter ( 3655): #0 StandardMethodCodec.decodeEnvelope message_codecs.dart:653 E/flutter ( 3655): #1 MethodChannel._invokeMethod platform_channel.dart:315 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #2 MethodChannelHttpsCallable.call method_channel_https_callable.dart:22 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #3 HttpsCallable.call https_callable.dart:49 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #4 _SendFeedbackModalBottomSheetState.build.<anonymous closure> send_feedback.dart:90 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): E/flutter ( 3655): #0 StandardMethodCodec.decodeEnvelope message_codecs.dart:653 E/flutter ( 3655): #1 MethodChannel._invokeMethod platform_channel.dart:315 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #2 MethodChannelHttpsCallable.call method_channel_https_callable.dart:22 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #3 HttpsCallable.call https_callable.dart:49 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655): #4 _SendFeedbackModalBottomSheetState.build.<anonymous closure> send_feedback.dart:90 E/flutter ( 3655): <asynchronous suspension> E/flutter ( 3655):
Flutter调用代码
final HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('sendFeedback'); final resp = await callable.call<String, dynamic>{ 'email': 'customer@example.com', 'message': message, };
云函数代码
const sendgridApiKey = functions.config().sendgrid.key; sgMail.setApiKey(sendgridApiKey); export const sendFeedback = functions.https.onCall(async (data, context) => { // Check if the user is authenticated if (!context.auth) { throw new functions.https.HttpsError("unauthenticated", "User is not authenticated"); } const message = data.message; try { // Compose the email message const emailMessage = { to: "hello@example.com", from: "no-reply@example.com", subject: "Feedback from user", text: message, }; // Send the email using SendGrid await sgMail.send(emailMessage); return { success: true, message: "Email sent successfully", }; } catch (error) { console.error("Error sending email:", error); throw new functions.https.HttpsError("internal", "An error occurred while sending the email"); } });
问题背景
- 该问题在模拟器和真机上均会出现
- 已确认「App Engine默认服务账号」角色为「Editor」
- 更新:已使用App Check调试token解决了App attestation失败问题,但权限拒绝问题仍然存在
解决方案建议
1. 确保调用前用户已完成Firebase认证
云函数代码中明确校验了context.auth,只有认证用户才能调用。Flutter端调用函数前必须确保用户已通过Firebase Auth完成登录:
- 调用函数前先检查
FirebaseAuth.instance.currentUser是否不为null,若未登录则引导用户完成登录流程(如邮箱密码登录、匿名登录等)
2. 配置云函数的IAM调用权限
检查云函数的IAM权限设置,确保调用者拥有函数的执行权限:
- 打开Firebase控制台,进入「函数」页面,找到
sendFeedback函数 - 点击「权限」标签,添加对应成员(测试阶段可临时添加
allUsers,生产环境需严格限制) - 为该成员授予「Cloud Functions Invoker」角色
3. 验证App Check的云函数侧配置
虽然已解决Token获取问题,仍需确认云函数是否启用了App Check验证:
- 若云函数启用了App Check验证,需确保Firebase控制台的App Check设置中已添加调试token(针对测试环境)
- 生产环境需确保App Check的提供者(如Play Integrity、App Attest)配置正确
4. 重新部署云函数并检查状态
确认云函数已正确部署,无部署错误:
- 使用命令
firebase deploy --only functions重新部署函数 - 查看部署日志,确保没有配置错误或依赖缺失
5. 确认Firebase Auth初始化完成
Flutter端需确保Firebase Auth已完成初始化,避免在Auth未就绪时调用函数:
- 可通过监听
FirebaseAuth.instance.authStateChanges()确认用户状态稳定后,再执行函数调用
内容的提问来源于stack exchange,提问作者Minh Danh
相关产品推荐
相关产品推荐

