Firebase App Check errors: fix 403s, “App attestation failed” and invalid tokens
Every App Check error happens at one of two steps: your app getting a token from its attestation provider (Play Integrity, App Attest, reCAPTCHA), or a Firebase service checking that token. When the first step fails, the second fails too, so don’t stop at the service’s error: look for the token exchange error and fix your platform’s registration. Emulators, simulators and localhost can’t pass attestation at all, so they use a debug token.
In short
- Find the step that failed first. A token exchange that ends in a 403 is a provider setup problem; a service rejecting requests with no exchange error means the token is missing or invalid. Tell them apart
- Use a debug token while developing. Emulators, simulators, localhost and debug-signed builds can’t pass real attestation. How to register one
- Each platform has values that must match. The signing certificate’s SHA-256 on Android, the Team ID and App Attest’s production environment on Apple, the reCAPTCHA key’s domains on the web. Causes by platform
- AI Logic has enforced App Check automatically since November 2, 2026. You can postpone it until January 21, 2027 at the latest. What to do
Find the failed step from the message
| Message | Failed step |
|---|---|
Android: Error returned from API. code: 403 body: App attestation failed. | Getting the token. The App Check server didn’t accept the Play Integrity result. |
Apple: The server responded with an error … HTTP status code: 403 | Getting the token. The App Attest or DeviceCheck result wasn’t accepted. |
Web: HTTP status: 403. (appCheck/fetch-status-error), then appCheck/throttled | Getting the token. The reCAPTCHA result wasn’t accepted, and the SDK won’t retry for 24 hours. |
Cloud Storage: Firebase App Check token is invalid. (storage/unauthorized-app in the web SDK) | Using the token. It’s missing or invalid. |
Callable functions: functions/unauthenticated | Using the token. A function with enforceAppCheck: true rejected it. A bad Auth token gives the same code; the function’s log line AppCheck token was rejected tells them apart. |
Realtime Database: Provided AppCheck credentials for the app named ... are invalid | Using the token. It’s invalid. |
Firebase AI Logic: 403 PERMISSION_DENIED: ... you must enforce Firebase App Check. | Using the token. See the AI Logic section. |
If the app can’t get a token, its service requests carry no valid one (the web SDK sends a placeholder token instead). So when a service rejects requests, check first whether a token exchange error was logged too. After a failure, the SDKs hold off retrying: 24 hours after a 403 or 404 on the web, 24 hours after a 400 or 404 on Android and Apple, and up to 4 hours after other errors. That state lives only in memory, so after you fix the setup, restart the app or reload the page before you check.
Use a debug token while developing
Emulators and simulators don’t count as valid devices, and debug builds that aren’t on Google Play don’t pass Play Integrity. reCAPTCHA keys shouldn’t list localhost. In these environments, turn on the debug provider and register the token it logs in the console.
- Turn on the debug provider in development builds only.
// 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(), ); - Run the app and find the debug token in the log. Current SDKs print
Firebase App Check debug token: <UUID>(in logcat on Android, the Xcode console on Apple, the browser console on the web). - Register it. In the Firebase console, open App Check, go to the Apps tab, and choose Manage debug tokens from your app’s ⋮ menu. Each app can have up to 20.
- Tokens change. A new one is made when you clear the app’s data or reinstall on Android, reinstall on Apple, or use another browser profile or clear site data on the web. Register the new one again.
- In CI, pass a token you registered. Set the token string in
self.FIREBASE_APPCHECK_DEBUG_TOKENon the web, the instrumentation argumentfirebaseAppCheckDebugSecreton Android, the scheme environment variableAppCheckDebugTokenon Apple, and thedebugTokenparameter in Flutter. - Treat the token like a password. Don’t commit it, and keep the debug provider and its token out of production builds.
Causes by platform
Android (Play Integrity)
| Symptom | Cause | Fix |
|---|---|---|
| Fails only on emulators or debug builds | Emulators aren’t valid devices, and Google Play doesn’t know the debug signature. | Debug token |
| The app from Play fails | You registered the upload key’s SHA-256. With Play App Signing, Google re-signs the app with the app signing key. | Register the SHA-256 of the app signing key certificate from the Play Console’s Manage Play app signing page in App Check |
| An app distributed outside Play fails | By default, only app versions Google Play recognizes (PLAY_RECOGNIZED) pass. | In App Check’s Play Integrity settings, set PLAY_RECOGNIZED to Not required and raise the minimum device integrity to Device integrity |
Fails as users grow (TOO_MANY_REQUESTS, -8) | Cloud projects not linked in the Play Console are capped at 10,000 Play Integrity requests a day. | Link the Firebase project under Play Integrity API in the Play Console (Link Cloud project), then request more quota if you need it. Only apps on Google Play can be linked. |
Apple (App Attest, DeviceCheck)
| Symptom | Cause | Fix |
|---|---|---|
| Fails on the Simulator | The Simulator isn’t a valid device. | Debug token |
| Only builds installed from Xcode fail | Adding the App Attest capability sets the environment to development, and App Check doesn’t accept results from it. TestFlight and App Store builds always use production. | Set App Attest Environment to production in the entitlements file |
| Fails on every device | The Team ID registered in Firebase isn’t the app’s. | Enter the right Team ID for the Apple app in the Firebase project settings |
| Fails on Macs or in app extensions | App Attest isn’t supported there. | Add DeviceCheck as a fallback provider. DeviceCheck needs a key (.p8) made on the Apple Developer site and its key ID registered in App Check |
| Flutter: the provider you chose isn’t used on real devices | Calling FirebaseApp.configure() in AppDelegate first makes it ignore providerApple. | Remove configure() from AppDelegate and use only Firebase.initializeApp() in Dart |
Web (reCAPTCHA)
| Symptom | Cause | Fix |
|---|---|---|
| Fails only on the deployed site | The domain isn’t in the reCAPTCHA key’s list of domains. | Add the domain to the key. It can take up to 30 minutes to apply |
| Fails on localhost | Production keys don’t list localhost. | Debug token |
| Fails after changing keys | The provider class and the value registered in Firebase don’t match. | An Enterprise key takes ReCaptchaEnterpriseProvider in code and the site key in Firebase; a v3 key takes ReCaptchaV3Provider in code and the secret key in Firebase |
| Still fails after the fix | After a 403 or 404, the SDK doesn’t retry the token exchange for 24 hours. | Reload the page. That state lives only in memory |
AI Logic: enforced automatically since November 2, 2026
Since November 2, 2026, Firebase enforces App Check for Firebase AI Logic in projects that weren’t enforcing it. Requests without a valid token are blocked, including those from released app versions without App Check. Two AI Logic errors name App Check:
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.- The first means a request without a valid App Check token called a model that’s commonly abused. Set up App Check and enforce it, with the debug provider while developing.
- The second means the project was judged inactive and doesn’t enforce App Check. If you already enforce it and still see this, check replay protection: when it’s on, even in Monitor only mode, only limited-use tokens count.
If versions without App Check are still in users’ hands, you can postpone enforcement. Change the Enforces date on the Firebase AI Logic row in App Check’s APIs tab; January 21, 2027 is the last date allowed. If the row already says Enforced, change the date, then in that row’s Set up set Baseline protection to Unenforced (monitoring only) and replay protection to Disabled. Google advises against this, so ship a version with App Check before then.
Before you enforce it on other services
- Read the metrics first. App Check’s APIs tab splits each service’s requests into Verified, Outdated client (no token), Unknown origin and Invalid. Once enforced, only verified requests get through, so enforce when nearly all recent requests are verified.
- Old app versions get blocked. Versions without the App Check SDK are rejected the moment you enforce.
- It takes up to 15 minutes to apply. Don’t judge the result right after you turn it on.
- Cloud Functions can enforce it on callable functions only. Add
enforceAppCheck: trueand redeploy.onRequestfunctions aren’t covered by enforcement, so verify the token yourself with the Admin SDK.
Sources
- App Check overview, enable enforcement, monitor metrics, debug token limit (REST)
- Play Integrity provider, Play Integrity quota, Android debug provider
- App Attest provider, DeviceCheck provider, Apple debug provider, App Attest environment (Apple), where App Attest is supported (Apple)
- reCAPTCHA Enterprise provider, reCAPTCHA v3 provider, create a reCAPTCHA key, web debug provider
- Flutter debug provider,
activate()infirebase_app_check - App Check for AI Logic, AI Logic error codes, App Check for Cloud Functions, verify tokens in your own backend
- SDK source: web throttle, web placeholder token, Storage rejection, Android error message, Android backoff, Apple backoff, callable function rejection
