Skip to content

App Check debug token expires after one hour, making the app unusable #14743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ulian-onua opened this issue Apr 20, 2025 · 10 comments
Open

App Check debug token expires after one hour, making the app unusable #14743

ulian-onua opened this issue Apr 20, 2025 · 10 comments

Comments

@ulian-onua
Copy link

Description

We’ve set up App Check in our app, but we’re experiencing issues with it in Debug mode.

The problem is that after launching, the app works for about an hour (the token expiration time), and then Firebase calls start returning code == 403.

We’ve configured AppCheckDebugProviderFactory and provided the FIRAAppCheckDebugToken, which is registered in the Firebase Console, in our Xcode scheme (as described here: https://firebase.google.com/docs/app-check/ios/debug-provider).

It seems that the app uses the debug token initially, but after an hour the token expires, and the system attempts to refresh it but fails.

To resolve this, we need to connect the device to Xcode and run the app through the debugger, or run the app on a simulator with the debugger attached. Sometimes even that doesn’t help — we have to delete and reinstall the app to make it work again.

Is there a way to resolve this issue and ensure stable functionality on a simulator or test device in Debug mode, without needing to connect the app to the debugger or reinstall it every hour?

Thank you for the help in advance.

Reproducing the issue

  1. Use this code in the app:
 let providerFactory = AppCheckDebugProviderFactory()
 AppCheck.setAppCheckProviderFactory(providerFactory)
  1. I have these settings in Xcode scheme:

Image

  1. We get this message in the Xcode console

Image

  1. Run the app through Xcode debugger and use it for an hour (or leave the app in the simulator to be opened for an hour and check in an hour). After an hour, the app stops working normally because Firestore returns 403 for all requests. Please look at "Relevant Log Output" for examples.

Firebase SDK Version

11.10.0

Xcode Version

16.3

Installation Method

Swift Package Manager

Firebase Product(s)

App Check

Targeted Platforms

iOS

Relevant Log Output

[Firebase/Crashlytics] Version 11.10.0
....
11.10.0 - [FirebaseAppCheck][I-FAA005001] Firebase App Check debug token: 'xxxxxxxxxxxxx'.

AFTER AN HOUR: 

11.10.0 - [FirebaseAuth][I-AUT000018] Error getting App Check token; using placeholder token instead. Error: Error Domain=com.google.app_check_core Code=0 "The server responded with an error:
 - URL: https://firebaseappcheck.googleapis.com/v1/projects/..../....:exchangeDebugToken
 - HTTP status code: 403
 - Response body: {
 "error": {
  "code": 403,
  "message": "App attestation failed.",
  "status": "PERMISSION_DENIED"
 }
}
" UserInfo={NSLocalizedFailureReason=The server responded with an error:
 - URL: https://firebaseappcheck.googleapis.com/v1/projects/..../....:exchangeDebugToken
 - HTTP status code: 403
 - Response body: {
 "error": {
  "code": 403,
  "message": "App attestation failed.",
  "status": "PERMISSION_DENIED"
 }
}
}

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet
Replace this line with the contents of your Package.resolved.

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
Replace this line with the contents of your Podfile.lock!
@google-oss-bot
Copy link

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@ncooke3
Copy link
Member

ncooke3 commented Apr 24, 2025

Hi @ulian-onua , I so far have been unable to reproduce this in an app using App Check and Auth. The sample app I'm using is here: main...nc/14743.

Are you able to reproduce the issue with my sample app or notice any key differences?

To use the sample app:

  1. Clone the Firebase repo
  2. Check out the nc/14743 branch
  3. xed FirebaseAppCheck/Apps/FIRAppCheckTestApp/, build and run, and wait for the refresh logic to trigger

@ulian-onua
Copy link
Author

@ncooke3
Thank you for your response and the example project! We'll try to reproduce the issue using your sample and write about the results here.

I noticed that your example project includes a requestDebugToken() method where the token is requested using the following code:

 func requestDebugToken() {
      guard let firebaseApp = FirebaseApp.app() else {
        return
      }

      if let debugProvider = AppCheckDebugProvider(app: firebaseApp) {
        print("Debug token: \(debugProvider.currentDebugToken())")

        debugProvider.getToken { token, error in
          if let token {
            print("Debug FAC token: \(token.token), expiration date: \(token.expirationDate)")
          }

          if let error {
            print("Debug error: \(error)")
          }
        }
      }
    }

We don’t have such a method in our real app. We simply set the following code and assume that token refreshing is handled automatically:

let providerFactory = AppCheckDebugProviderFactory()
AppCheck.setAppCheckProviderFactory(providerFactory)

Should we be calling a method similar to requestDebugToken() in our app every hour or so? Or is the token supposed to refresh automatically behind the scenes?

I couldn’t find any clear information about this in the official documentation.

Thank you in advance.

@ulian-onua
Copy link
Author

@ncooke3
After implementing the requestDebugToken() method in our real app and setting up a timer to refresh the token every 20 minutes, the app has become more stable.

If the app remains open, it works well the whole time.

However, if the app is closed and I open it, for example, a day later, the issue I previously reported can still occur.

So here is my general question again:
Should we call requestDebugToken() periodically to refresh the token manually, or is it supposed to be refreshed automatically?

I couldn’t find any guidance in the official Firebase iOS documentation.

I appreciate any help you can provide.

@ncooke3
Copy link
Member

ncooke3 commented May 1, 2025

Should we be calling a method similar to requestDebugToken() in our app every hour or so? Or is the token supposed to refresh automatically behind the scenes?

Hi @ulian-onua, manually calling it should be unnecessary. The SDK should refresh it automatically.

@ncooke3
Copy link
Member

ncooke3 commented May 1, 2025

@ulian-onua, were you able to reproduce the issue in the sample app? It does call requestDebugToken() but only at startup so when I experimented with it, I was able to see the initial fetch and then the refresh fetches (which were about every ~30ish minutes).

@ulian-onua
Copy link
Author

@ncooke3 thank you for your answers.

The sample app seems to work well. I wasn’t able to reproduce the issue in it, but I also didn’t include any Firestore calls or listeners, for example.

In our case, we are listening to a User custom object stored in Firestore using the following method of the FIRDocumentReference class:

- (id<FIRListenerRegistration>)addSnapshotListener:
    (void (^)(FIRDocumentSnapshot *_Nullable snapshot, NSError *_Nullable error))listener
    NS_SWIFT_NAME(addSnapshotListener(_:));

The issue typically occurs about an hour into using the app in a debug environment. The User object becomes nil, and we observe App Check errors in the console, as described in the issue details.

It can also happen after relaunching the app a few hours later, even if it was working normally before being closed.

We’ve noticed that manually refreshing the token using the method from your sample code improves stability. However, the issue still occurs in certain cases, such as after relaunching the app following an extended period of inactivity.

At this point, we're unsure about the root cause or what might be triggering the problem.

This issue did not occur until we enabled App Check for our app.

@ncooke3
Copy link
Member

ncooke3 commented May 2, 2025

Thanks, @ulian-onua. Are you able to provide a very minimal app that reproduces the issue, or perhaps modify the sample app to do so?

@ulian-onua
Copy link
Author

ulian-onua commented May 3, 2025

@ncooke3, we will try to prepare and provide it soon.

Also, I would like to add here that we can see a certain percentage of "Unverified requests" on the Firestore Console. It happens not only for the Dev version but also for Beta (where the prod environment is used). I'm not sure if it is related to this issue but decided to let you know about it (as I think it can be related).

I opened a corresponding issue on StackOverflow: https://stackoverflow.com/questions/79600010/firebase-app-check-unverified-requests-on-ios-1-10

Image

@ncooke3
Copy link
Member

ncooke3 commented May 6, 2025

@ulian-onua , when you encounter failures, are they happening when the app is in the foreground or background?

If the issues are related, I'm thinking that once the App Check bug occurs, subsequent storage requests are made and are counted as unverified. Does this make sense in the context of how your app operates? Does it make sense that only storage would have a significant amount of unverified requests?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants