firebase / firebase-android-sdk

Firebase Android SDK
https://firebase.google.com
Apache License 2.0
2.25k stars 572 forks source link

Can't pass appcheck outside play store after migrating from safetynet to play integrity #4746

Closed arturmaslov closed 1 year ago

arturmaslov commented 1 year ago

[READ] Step 1: Are you in the right place?

[REQUIRED] Step 2: Describe your environment

[REQUIRED] Step 3: Describe the problem

We're having issues at our company after migrating AppCheck from SafetyNet to PlayIntegrity provider. Before migration our testers been able to run app built from firebase using SafetyNet without manual token input as we (developers) do with DebugProvider. We tried to upload our develop app into play console internal testing, but that didn't help. We've used same SHA keys which were generated at play console. So, it seems that play integrity appcheck currently works only with production app which must be published on play store.

Is this intended logic and are there any solutions for apps outside play store which are not yet published to pass AppCheck without manual token input? That's very inconvenient for our testers. It's major problem for us as safetynet gets discontinued in June 2023. Here are some additional issues regarding this topic on stackoverflow: https://stackoverflow.com/questions/72631258/android-app-check-play-integrity-not-work https://stackoverflow.com/questions/74992711/google-play-integrity-api-invalid-app-check-token-error-after-adding-app-to-fi

Steps to reproduce:

  1. Use PlayIntegrityAppCheckProviderFactory for AppCheck
  2. Run app build from firebase
  3. Result:
    
    pc_0 - Detected invalid AppCheck token. Reconnecting (2 attempts remaining)
    pc_0 - Detected invalid AppCheck token. Reconnecting (1 attempts remaining)
    pc_0 - Detected invalid AppCheck token. Reconnecting (0 attempts remaining)

pc_0 - Firebase Database connection was forcefully killed by the server. Will not attempt reconnect. Reason: Invalid appcheck token


#### Relevant Code:
Before (debug for developers and safety net for other cases):

private fun setCheckProviders(firebaseAppCheck: FirebaseAppCheck) { if (BuildConfig.DEBUG) { firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance()) } else { firebaseAppCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance()) } }

Wanted (debug for developers, play integrity for other cases):

private fun setCheckProviders(firebaseAppCheck: FirebaseAppCheck) { if (BuildConfig.DEBUG) { firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance()) } else { firebaseAppCheck.installAppCheckProviderFactory(PlayIntegrityAppCheckProviderFactory.getInstance()) } }

Now (debug for developers, safetynet for testers, play integrity for public play store:

private fun setCheckProviders(firebaseAppCheck: FirebaseAppCheck) { if (BuildConfig.DEBUG) { firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance()) } else { // it's release if (BuildConfig.FLAVOR_env.isDevEnv() || BuildConfig.FLAVOR_env.isUatEnv()) firebaseAppCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance()) else firebaseAppCheck.installAppCheckProviderFactory(PlayIntegrityAppCheckProviderFactory.getInstance()) } }

google-oss-bot commented 1 year ago

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

argzdev commented 1 year ago

Thanks for reaching out, @arturmaslov. Before I bring this up to our engineering team for discussion, can you clarify what you mean by "without manual token input"?

arturmaslov commented 1 year ago

Currently with DebugAppCheckProviderFactory we need to add generated firebase token from logcat into firebase console (at AppCheck - Apps - Manage debug tokens) to pass AppCheck.

argzdev commented 1 year ago

Thanks for clarifying, @arturmaslov. I wasn't able to try the old version of safetynet before so I'm not sure, but was this process something that was not needed before when using DebugAppCheckProviderFactory? I wonder if there's a way we can automate this process. Let me ask our engineers.

neone35 commented 1 year ago

We don't need any manual process when using safetynet. That's the issue here, because it's being discontinued and we lose this automation. PlayIntegrity doesn't suit us because we won't publish our develop builds on play store for appcheck to pass.

argzdev commented 1 year ago

Got it, thanks for answering all the questions @neone35. I'll let you know if we have updates from our engineers.

claudiochiumarulo commented 1 year ago

I am facing the same issues with the migration, safetynet would validate test devices (not emulators), so we never felt the need to even install the debug library on staging environment. I think the issue would be mitigated by providing the option to set a fixed debug token like is permitted on the iOS version of the library. It has been asked here

arturmaslov commented 1 year ago

Any updates on this? @argzdev

argzdev commented 1 year ago

Sorry, @arturmaslov. Our engineers are still taking a look into it. We'll reply back here once we have updates to share. Thanks for following up!

rosalyntan commented 1 year ago

Hi @arturmaslov -- thanks for filing this issue. Please see the "Test your Play Integrity API integration" section in this support documentation for instructions on how to allowlist the emails of your testers so that they will receive the correct integrity response.

arturmaslov commented 1 year ago

@rosalyntan but will builds from firebase work after adding this tester list to play integrity?

rosalyntan commented 1 year ago

@arturmaslov Can you clarify what you mean by "builds from Firebase"? Per the linked documentation, you should publish your app to the internal test track or the track that you intend to test on.

neone35 commented 1 year ago

We've added our app to console with package.develop and created internal testing for it before. What we didn't know is that we need to enable play integrity for internal testing separately. We expected it'd work out of the box for both published and internal apps. And that was the reason why check failed?

So as our testers accept invitation to test our internal develop app with play integrity for testing enabled, firebase builds should work the same as they worked with safetynet, because now package.develop is on play store with internal testing enabled?

neone35 commented 1 year ago

@rosalyntan can you please confirm or deny my theory

arturmaslov commented 1 year ago

We've just enabled play integrity testing and made release build uploaded to play console with this code and we still can't pass AppCheck.

private fun setCheckProviders(firebaseAppCheck: FirebaseAppCheck) {
        if (BuildConfig.DEBUG) {
            firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance())
        } else { 
            firebaseAppCheck.installAppCheckProviderFactory(PlayIntegrityAppCheckProviderFactory.getInstance())
        }
    }
arturmaslov commented 1 year ago

And finally it seems to work:

  1. Add App signing key certificate SHA-256 from Play Console to our Firebase at AppCheck - Apps - Play Integrity.
  2. Choose Licensed Play-recognized app at Play console - App integrity - New test

Now we'll test these cases:

  1. Without play console App signing key certificate at Firebase and with Unlicensed Play-recognized app option
  2. With play console App signing key certificate at Firebase and without New test at Play console Also, we'll check if firebase appcheck dependencies can work without play services dependencies to decrease our app weight.
arturmaslov commented 1 year ago

So turns out these additional cases don't work and we must make sure two first steps are intact for play integrity appcheck to work.