Firexport博客

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。在这些环境中,请启用调试提供方,并把日志中输出的令牌注册到控制台。

  1. 只在开发版本中启用调试提供方。
    // 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(),
    );
  2. 运行应用,在日志中找到 debug token。新版 SDK 会以 Firebase App Check debug token: <UUID> 的格式输出(Android 在 logcat 中,Apple 在 Xcode 控制台中,Web 在浏览器控制台中)。
  3. 注册令牌。在 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 自行验证令牌。

资料来源

全部文章 →