[AppCheck] Firestore stops working after leaving the website idle overnight - AppCheck HTTP error 403 (appCheck/fetch-status-error) + infinite loop / high CPU usage
Problem
AppCheck problem AppCheck works fine and enforced. However, after leaving the webapp idle for a while (e.g., if I leave the tab open and go to sleep and put the laptop to sleep, then come to work the next day), Firestore stops working (as if it gets disconnected and doesn't reconnect or refresh AppCheck token). Console error observed in production: `@firebase/app-check: FirebaseError: AppCheck: Fetch server returned an HTTP error status. HTTP status: 403. (appCheck/fetch-status-error).` Console error observed on localhost: `zone.js:1061 Unhandled Promise rejection: cancelled ; Zone: <root> ; Task: Promise.then ; Value: cancelled undefined` Environment Angular version: 14.0.2 (latest) Firebase SDK version: 9.8.3 (latest) AngularFire version: 7.4.1 (latest) Firebase Product: AppCheck
Error Output
error observed in production: `@firebase/app-check: FirebaseError: AppCheck: Fetch server returned an HTTP error status. HTTP status: 403. (appCheck/fetch-status-error).`
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Implement AppCheck Token Refresh on Idle State
The AppCheck token may expire or become invalid after a prolonged idle state, leading to a 403 error when attempting to access Firestore. This occurs because the token is not automatically refreshed when the application is idle, causing the app to fail to authenticate requests after waking from sleep or after being idle for an extended period.
Awaiting Verification
Be the first to verify this fix
- 1
Set Up AppCheck Token Refresh
Implement a mechanism to refresh the AppCheck token when the application becomes active again after being idle. This can be achieved by listening for the 'visibilitychange' event in the browser.
typescriptdocument.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { firebase.appCheck().activate(); } }); - 2
Handle AppCheck Errors Gracefully
Add error handling for AppCheck fetch errors to retry fetching the token if a 403 error is encountered. This will prevent the application from entering an infinite loop of errors.
typescriptfirebase.firestore().collection('yourCollection').get().catch((error) => { if (error.code === 'appCheck/fetch-status-error') { // Retry logic or token refresh console.log('Retrying AppCheck token fetch...'); firebase.appCheck().activate(); } }); - 3
Monitor AppCheck Token Expiration
Implement a function to monitor the expiration of the AppCheck token and proactively refresh it before it expires, ensuring that the application remains authenticated.
typescriptsetInterval(() => { firebase.appCheck().getToken().then((token) => { console.log('AppCheck token refreshed:', token); }); }, 3600000); // Refresh every hour - 4
Test Idle State Recovery
After implementing the above changes, test the application by leaving it idle and then waking it up to ensure that the AppCheck token is refreshed and Firestore operations succeed without errors.
Validation
Confirm the fix by leaving the web application idle overnight and then waking it up. Ensure that Firestore operations work without throwing AppCheck errors. Monitor the console for any 403 errors and check that the token refresh logic is executed correctly.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep