Flutter启用App Check与Play Integrity后Firebase onCall验证及推送异常
Firebase App Check 与 Play Integrity 集成问题
已在Firebase中启用App Check和Play Integrity,但调用Callable函数时遇到两个问题:
- 应用验证未执行(详见Firebase函数日志);
- onCall函数内的推送通知未触发。
错误信息
客户端日志报错:
W/FirebaseContextProvider(25810): Error getting App Check token. Error: com.google.firebase.FirebaseException: Too many attempts.
Google Cloud函数日志摘要:
functionName158nxe4tcyx4 Callable request verification passed
jsonPayload: { message: "Callable request verification passed" verifications: { auth: "VALID" app: "MISSING" // 问题核心:应用验证缺失 } }
关键现象
移除以下两段代码后,推送通知可正常接收:
- 云函数的App Check强制验证配置:
.runWith({ enforceAppCheck: true })
- 云函数内的App Check校验逻辑:
if (context.app == undefined) { throw new functions.https.HttpsError( 'failed-precondition', 'The function must be called from an App Check verified app.') }
相关代码
Flutter 端 Firebase 初始化
import 'package:firebase_app_check/firebase_app_check.dart'; Future<void> initFirebase() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); await FirebaseAppCheck.instance.activate( webRecaptchaSiteKey: 'recaptcha-v3-site-key', androidProvider: AndroidProvider.playIntegrity, // 模拟器用'debug'枚举,真机用'playIntegrity' );
Flutter 端 Callable 函数调用
HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'my-area') .httpsCallable('functionName'); await callable.call<String, dynamic>({ 'token': pushToken, 'username': '$userName', });
Firebase 云函数代码
exports.functionName = functions .region('my-area') .runWith({ enforceAppCheck: true }) .https.onCall(async (data, context) => { if (context.app == undefined) { throw new functions.https.HttpsError( 'failed-precondition', 'The function must be called from an App Check verified app.') } // 推送通知任务未执行(问题2) const token = data.token; const isApproved = data.isApproved; const payLoad = { data: { 'type': 'approvalStatus' }, notification: { title: `Approval Status Update`, body: isApproved ? `Some description Text here`, clickAction: 'FLUTTER_NOTIFICATION_CLICK' } }; return fcm.sendToDevice(token, payLoad); });
解决步骤
1. 修复App Check Token获取失败(Too many attempts)
- 真机Play Integrity配置检查:
- 确认已在Google Play Console为应用启用Play Integrity API,并将生成的API密钥配置到Firebase控制台的App Check设置(对应Android应用的Play Integrity提供方)。
- 测试真机必须安装正式签名的应用包,debug包使用Play Integrity会验证失败,需配置debug签名的Play Integrity豁免规则。
- 调整重试逻辑:
App Check默认重试可能因网络或验证失败触发频繁请求,可在Flutter端手动捕获错误并添加指数退避重试:try { // 主动获取Token验证是否能正常获取 await FirebaseAppCheck.instance.getToken(true); } catch (e) { await Future.delayed(Duration(seconds: 2)); // 再次尝试获取Token await FirebaseAppCheck.instance.getToken(true); }
2. 修复云函数端App Check验证缺失
- 配置云函数权限:
在Google Cloud IAM中,为云函数默认服务账号添加Firebase App Check Token Verifier角色,确保其拥有firebaseappcheck.verifyToken权限。 - 调试验证逻辑:
在云函数中添加日志打印,确认context.app的具体内容:console.log('App Check上下文信息:', context.app); - 检查语法错误:
云函数推送Payload中的body字段使用三元运算符但缺少else分支,会直接导致函数崩溃,这也是推送未执行的潜在原因,需补全:body: isApproved ? `已通过审核` : `审核未通过`,
3. 推送通知恢复逻辑
推送未执行本质是App Check验证失败导致函数提前抛出错误,解决App Check验证问题后,推送逻辑会自动执行。额外确认:
- 云函数中
fcm已正确初始化(如const fcm = admin.messaging();)。 - 推送Token是有效的设备Token。
内容的提问来源于stack exchange,提问作者Neil-NotNeo
相关产品推荐
相关产品推荐

