Firebase App Check 错误排查:403、App attestation failed、无效令牌
App Check 错误出在两个步骤中的一个:应用通过证明提供方(Play Integrity、App Attest、reCAPTCHA)获取令牌的步骤,或 Firebase 服务验证该令牌的步骤。前一步失败,后一步也会失败,所以不要只看服务的错误,先找到令牌交换的错误,再修正各平台的注册值。Android 模拟器、iOS 模拟器和 localhost 本来就无法通过证明,所以要用调试令牌。
要点
- 先找出失败的步骤。令牌交换以 403 结束,是提供方的设置问题;没有交换错误、只有服务拒绝请求,则是令牌缺失或无效。根据消息区分
- 开发环境使用调试令牌。Android 模拟器、iOS 模拟器、localhost 和调试签名的版本都无法通过真正的证明。注册方法
- 每个平台都有必须匹配的值。Android 是签名证书的 SHA-256,Apple 是 Team ID 和 App Attest 的 production 环境,Web 是 reCAPTCHA 密钥的网域。各平台的原因
- AI Logic 自 2026 年 11 月 2 日起自动强制执行 App Check。最晚只能推迟到 2027 年 1 月 21 日。该怎么做
根据消息找出失败的步骤
| 消息 | 失败的步骤 |
|---|---|
Android:Error returned from API. code: 403 body: App attestation failed. | 获取令牌。App Check 服务器没有接受 Play Integrity 的结果。 |
Apple:The server responded with an error … HTTP status code: 403 | 获取令牌。App Attest 或 DeviceCheck 的结果没有被接受。 |
Web:HTTP status: 403. (appCheck/fetch-status-error),随后是 appCheck/throttled | 获取令牌。reCAPTCHA 的结果没有被接受,SDK 在 24 小时内不会重试。 |
Cloud Storage:Firebase App Check token is invalid.(Web SDK 中为 storage/unauthorized-app) | 使用令牌。令牌缺失或无效。 |
Callable 函数:functions/unauthenticated | 使用令牌。设置了 enforceAppCheck: true 的函数拒绝了请求。Auth 令牌有误时返回的也是这个代码,要靠函数日志中的 AppCheck token was rejected 来区分。 |
Realtime Database:Provided AppCheck credentials for the app named ... are invalid | 使用令牌。令牌无效。 |
Firebase AI Logic:403 PERMISSION_DENIED: ... you must enforce Firebase App Check. | 使用令牌。请看 AI Logic 一节。 |
拿不到令牌时,服务请求中就没有有效的令牌(Web SDK 会附上占位令牌发送)。所以即使看到的是服务端的错误,也请先确认是否同时记录了获取令牌的错误。失败后,SDK 会推迟重试。Web 在 403、404 之后为 24 小时,Android 和 Apple 在 400、404 之后为 24 小时,其他错误最多 4 小时。这个状态只保存在内存中,所以修正设置后,请重启应用或刷新页面再确认。
开发时使用调试令牌
Android 模拟器和 iOS 模拟器不算有效设备,没有在 Google Play 上发布的调试版本也无法通过 Play Integrity。reCAPTCHA 密钥原则上不加入 localhost。在这些环境中,请启用调试提供方,并把日志中输出的令牌注册到控制台。
- 只在开发版本中启用调试提供方。
// Android (Kotlin): com.google.firebase:firebase-appcheck-debug Firebase.appCheck.installAppCheckProviderFactory( if (BuildConfig.DEBUG) DebugAppCheckProviderFactory.getInstance() else PlayIntegrityAppCheckProviderFactory.getInstance(), ) // iOS (Swift): before FirebaseApp.configure() #if DEBUG AppCheck.setAppCheckProviderFactory(AppCheckDebugProviderFactory()) #endif // Web: before initializeAppCheck(), in development builds only self.FIREBASE_APPCHECK_DEBUG_TOKEN = true; // Flutter (firebase_app_check 0.5+) await FirebaseAppCheck.instance.activate( providerAndroid: kDebugMode ? const AndroidDebugProvider() : const AndroidPlayIntegrityProvider(), providerApple: kDebugMode ? const AppleDebugProvider() : const AppleAppAttestWithDeviceCheckFallbackProvider(), ); - 运行应用,在日志中找到 debug token。新版 SDK 会以
Firebase App Check debug token: <UUID>的格式输出(Android 在 logcat 中,Apple 在 Xcode 控制台中,Web 在浏览器控制台中)。 - 注册令牌。在 Firebase 控制台的 App Check 中打开应用(Apps)标签页,从应用的 ⋮ 菜单中选择管理调试令牌(Manage debug tokens)。每个应用最多可注册 20 个。
- 令牌会变。Android 清除应用数据或重新安装后、Apple 重新安装后、Web 换用其他浏览器配置文件或清除网站数据后,都会生成新的令牌。新令牌需要重新注册。
- 在 CI 中传入已注册的令牌。Web 把令牌字符串赋给
self.FIREBASE_APPCHECK_DEBUG_TOKEN,Android 使用插桩测试参数firebaseAppCheckDebugSecret,Apple 使用 scheme 环境变量AppCheckDebugToken,Flutter 使用debugToken参数。 - 像对待密码一样对待令牌。不要提交到代码仓库,也不要把调试提供方和令牌放进正式版本。
各平台的原因
Android(Play Integrity)
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 只在模拟器或调试版本上失败 | 模拟器不是有效设备,Google Play 也不认识调试签名。 | 调试令牌 |
| 从 Play 安装的应用失败 | 注册的是上传密钥的 SHA-256。使用 Play 应用签名时,Google 会用应用签名密钥重新签名。 | 在 Play Console 中点击前往 Play 应用签名(Manage Play app signing),把该页面上应用签名密钥证书的 SHA-256 注册到 App Check |
| 在 Play 之外分发的应用失败 | 默认设置只放行 Google Play 认识的应用版本(PLAY_RECOGNIZED)。 | 在 App Check 的 Play Integrity 设置中把 PLAY_RECOGNIZED 改为不需要(Not required),并把最低设备完整性级别提高到设备完整性(Device integrity) |
用户增多后失败(TOO_MANY_REQUESTS,-8) | 未关联 Play Console 的 Cloud 项目,Play Integrity 请求每天限 1 万次。 | 在 Play Console 的 Play Integrity API 部分,通过关联云项目(Link Cloud project)关联 Firebase 项目,需要时再申请提高配额。只有 Google Play 上的应用才能关联。 |
Apple(App Attest、DeviceCheck)
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 在模拟器上失败 | 模拟器不是有效设备。 | 调试令牌 |
| 只有从 Xcode 安装的版本失败 | 添加 App Attest capability 后,环境会设为 development,而 App Check 不接受这个环境的结果。TestFlight 和 App Store 的版本始终是 production。 | 把 entitlements 文件中的 App Attest Environment 设为 production |
| 所有设备上都失败 | 在 Firebase 中注册的 Team ID 与应用的不一致。 | 在 Firebase 项目设置的 Apple 应用中填写正确的 Team ID |
| 在 Mac 或 App 扩展中失败 | 这些环境不支持 App Attest。 | 加上 DeviceCheck 作为回退提供方。DeviceCheck 需要把在 Apple 开发者网站上创建的私钥(.p8)及其密钥 ID 注册到 App Check |
| Flutter:所选的提供方在真机上没有被使用 | 如果先在 AppDelegate 中调用 FirebaseApp.configure(),providerApple 就会被忽略。 | 删除 AppDelegate 中的 configure(),只使用 Dart 中的 Firebase.initializeApp() |
Web(reCAPTCHA)
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 只在已部署的网站上失败 | 该网域不在 reCAPTCHA 密钥的网域列表中。 | 在密钥设置中添加网域。最多需要 30 分钟才会生效 |
| 在 localhost 上失败 | 生产环境用的密钥不加入 localhost。 | 调试令牌 |
| 更换密钥后失败 | 提供方类与在 Firebase 中注册的值不匹配。 | Enterprise 密钥在代码中用 ReCaptchaEnterpriseProvider,在 Firebase 中填网站密钥。v3 密钥在代码中用 ReCaptchaV3Provider,在 Firebase 中填 Secret 密钥 |
| 修正后仍然失败 | 403、404 之后,SDK 在 24 小时内不会重试令牌交换。 | 刷新页面。这个状态只保存在内存中。 |
AI Logic:自 2026 年 11 月 2 日起自动强制执行
自 2026 年 11 月 2 日起,Firebase 会为尚未强制执行 App Check 的项目,自动对 Firebase AI Logic 强制执行 App Check。没有有效令牌的请求会被拦截,未集成 App Check 就已发布的应用版本也是如此。提到 App Check 的 AI Logic 错误有两种。
403 PERMISSION_DENIED: To access this model, you must enforce
Firebase App Check.
403 PERMISSION_DENIED: Firebase AI Logic has been deactivated in this
project. To resume using Firebase AI Logic, you must enforce Firebase
App Check.- 第一种是在没有有效 App Check 令牌的情况下调用了常被滥用的模型。请设置并强制执行 App Check。开发时使用调试提供方。
- 第二种是项目被判定为不活跃,并且没有强制执行 App Check。如果已经在强制执行却仍出现这个错误,请检查重放攻击防范(replay protection)。它开启后(包括 Monitor only 模式),只认可限制使用令牌(limited-use token)。
如果没有 App Check 的版本仍在用户手中,可以推迟强制执行。在 App Check 的 API(APIs)标签页中修改 Firebase AI Logic 那一行的 Enforces 日期即可,最晚为 2027 年 1 月 21 日。如果已经处于已强制执行(Enforced)状态,修改日期后,还要在该行的设置(Set up)中把基础保护(Baseline protection)改为 Unenforced (monitoring only),把重放攻击防范改为 Disabled,才能解除。Google 不推荐这种做法,请在此之前发布集成了 App Check 的版本。
对其他服务强制执行之前
- 先看指标。App Check 的 API(APIs)标签页会按服务把请求分为已验证(Verified)、过时的客户端(Outdated client,没有令牌)、未知来源(Unknown origin)和无效(Invalid)。强制执行后只有已验证的请求能通过,所以请在近期请求几乎都已验证时再强制执行。
- 旧版应用会被拦截。没有 App Check SDK 的版本,从强制执行的那一刻起,请求就会被拒绝。
- 最多需要 15 分钟才会生效。不要刚开启强制执行就判断结果。
- Cloud Functions 只能对 Callable 函数强制执行。加上
enforceAppCheck: true并重新部署后才会生效。onRequest函数不在 App Check 强制执行的范围内,需要用 Admin SDK 自行验证令牌。
资料来源
- App Check 概览、启用强制执行、监控指标、调试令牌数量上限(REST)
- Play Integrity 提供方、Play Integrity 配额、Android 调试提供方
- App Attest 提供方、DeviceCheck 提供方、Apple 调试提供方、App Attest 环境(Apple)、可以使用 App Attest 的环境(Apple)
- reCAPTCHA Enterprise 提供方、reCAPTCHA v3 提供方、创建 reCAPTCHA 密钥、Web 调试提供方
- Flutter 调试提供方、
firebase_app_check的activate() - AI Logic 的 App Check、AI Logic 错误代码、Cloud Functions 的 App Check、在自建后端验证令牌
- SDK 源代码:Web 的重试限制、Web 的占位令牌、Storage 的拒绝方式、Android 错误信息、Android 重试、Apple 重试、Callable 函数的拒绝方式
