react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

Android / AppCheck - SafetyNet deprecation, Play Integrity support

Open birdofpreyru opened this issue 3 years ago • 3 comments
trafficstars

Issue

As per Firebase App Check docs the SafetyNet provider has been deprecated, and superseded by Play Integrity. Though, RN Firebase App Check docs still read the following, and I have not found any existing issue regarding this:

This App Check module has built-in support for using the following services as attestation providers:

  • DeviceCheck on iOS
  • SafetyNet on Android

Not sure, does it require any changes in RN Firebase to support Play Integrity? Is only a matter of updating the RN Firebase documentation? Also what's up with iOS AppAttest provider?


Project Files

Javascript

Click To Expand

package.json:

# N/A

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • [ ] I'm not using Pods
  • [x] I'm using Pods and my Podfile looks like:
# N/A

AppDelegate.m:

// N/A

Android

Click To Expand

Have you converted to AndroidX?

  • [ ] my application is an AndroidX application?
  • [ ] I am using android/gradle.settings jetifier=true for Android compatibility?
  • [ ] I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->

Environment

Click To Expand

react-native info output:

 OUTPUT GOES HERE
  • Platform that you're experiencing the issue on:
    • [ ] iOS
    • [ ] Android
    • [ ] iOS but have not tested behavior on Android
    • [ ] Android but have not tested behavior on iOS
    • [ ] Both
  • react-native-firebase version you're using that has this issue:
    • e.g. 5.4.3
  • Firebase module(s) you're using that has the issue:
    • e.g. Instance ID
  • Are you using TypeScript?
    • Y/N & VERSION

birdofpreyru avatar Jul 30 '22 23:07 birdofpreyru

It will require quite a few changes unfortunately. Fortunately we have a year to do it! :-)

I can't just add support without doing a lot of documentation work and it will be a breaking change because play integrity requires some changes in your google account to set things up

See https://github.com/invertase/react-native-firebase/pull/6402#issuecomment-1187944539 (a comment)

also https://github.com/invertase/react-native-firebase/discussions/6345#discussioncomment-3035067

mikehardy avatar Jul 30 '22 23:07 mikehardy

@mikehardy do you foresee the process of switching from SafetyNet to Play Integrity quite a hassle for the average developer (when rnfirebase releases the breaking change) ?

Edit: I checked out the links mentioned above. Nevermind :)

jadonhansen avatar Aug 02 '22 08:08 jadonhansen

Just for anyone else reading along, do go read those links, but just to directly answer your question @jadonhansen I don't think it will be too big a hassle, if the docs are really clear. I think that's most of the work, good documentation, screenshots of the web console changes you need to make etc. Most of the breaking changes we do hear are pretty small "do this and you are set" type changes with exception of the current use_frameworks! hassle for v15

mikehardy avatar Aug 02 '22 15:08 mikehardy

Curious about something on this future App Check change. When the Play Integrity update is eventually merged and you deploy a new version of your app, will Firebase be able to process requests for devices that still have the SafetyNet version, alongside the newer build with Play? Or will it be a hard cutover, meaning anyone who hasn't updated to the latest version of your app will start seeing errors?

brianGammon avatar Nov 07 '22 22:11 brianGammon

It is my understanding that you may have multiple back-end verification styles that are valid at the same time. The language around configuration is "one or more" in terms of providers, they both have a + sign for me, so I think it's soft cutover, you disable SafetyNet provider when you feel your userbase is sufficiently migrated

image

mikehardy avatar Nov 07 '22 22:11 mikehardy

https://www.linkedin.com/pulse/react-native-firebase-app-check-play-integrity-android-

cc : @mikehardy

bharatbrovitech avatar Nov 10 '22 13:11 bharatbrovitech

Wow @bharatbrovitech so, instead of constructively posting a PR here, there's a linkedin article and a new native module and everything? That seems like a mal-investment, but everyone gets to spend their time doing what they like :smile:

I will say that I specifically take issue with this statement in your link:

Firebase android Safetynet is deprecated. So, rnfirebase is not useful for android anymore.

That is plainly false. You are overstating a deprecation with a migration timeline of more than a year as being "not useful". I don't get it personally, that sounds almost like fear-mongering.

I will say that I discussed this just today with the rest of the crew @ Invertase and this is on our high priority todo list. I'm going to open a PR with a sketch for it shortly, and we'll get this done.

mikehardy avatar Nov 10 '22 18:11 mikehardy

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Dec 08 '22 18:12 github-actions[bot]

Not stale at all!

birdofpreyru avatar Dec 08 '22 20:12 birdofpreyru

No, it's not. Previous stale bot broke, just installed a new one and it caught this. New stale both may or may not be respecting my "don't stale these labels..." list, so we'll see.

Either way, no intention of closing this until completed

mikehardy avatar Dec 08 '22 20:12 mikehardy

Just to mention, according to an email sent around today by SafetyNet team:

  • New users will no longer be able to sign up for the SafetyNet Attestation API after January 31, 2023.
  • After June 30, 2023 the API will stop working in all versions of an app, if the app has not migrated to Play Integrity API yet.

Thus, the day AppCheck in RN-Firebase risks to turn pumpkin is probably just a month away, maybe 6.

birdofpreyru avatar Dec 16 '22 12:12 birdofpreyru

Coincidentally I have tuned down most of my other work commitments and will have time to get to it before the deadline I think. I also saw that email and went "oh no - okay, gotta do this before end of January for new projects...."

mikehardy avatar Dec 16 '22 18:12 mikehardy

Thank you. It's always you to save us all @mikehardy ! I couldn't help much on native coding, but is there any other ways to help? Like donation to the project?

tarouboy avatar Dec 24 '22 09:12 tarouboy

I'll never say no to github sponsorships :-) and they do affect how I choose to spend my time. I will give credit to Invertase (and Google) though in general, they provide a base foundation of financial support for my work on the project which is what makes it possible for me to hack on the code here and still eat. Cheers :-)

mikehardy avatar Dec 24 '22 18:12 mikehardy

I'm a bit confused after reading the mail, can someone help me with my doubt?

As a part of the gradual phase out of the SafetyNet Attestation API new users will no longer be able to sign up for the SafetyNet Attestation API after January 31, 2023. This includes new developers signing up through SDKs.

Does this mean that the users will not be able to sign up and use the app? If not, then what does it refers to as "New users" here?

sreehari-kt avatar Jan 04 '23 10:01 sreehari-kt

@sreehari-kt I believe, it refers to developers, i.e. it won't be possible to set up a new app to rely on SafetyNet neither via Firebase web console nor programmatically via SDK / cli, however existing apps using it will continue to work for new end-users till future deadlines.

birdofpreyru avatar Jan 04 '23 10:01 birdofpreyru

Just got this warning in Google play.

I my app also don't use safetynet.

I think we should wait until Firebase do migration as currently there is nothing we can do.

But maybe there will be need for some action from Invertase as well?

radekzz avatar Jan 06 '23 16:01 radekzz

Possible temporary solution > https://www.linkedin.com/pulse/react-native-firebase-app-check-play-integrity-android-/

grinono avatar Jan 09 '23 16:01 grinono

@grinono this shameless promo has been posted above already. Taking into account that "popular dependency rnfirebase" is actively maintained, and useful far beyond the appcheck, the author of that LinkedIn post could just do a PR fixing the issue, rather than spending the same time writing an article about a workaround.

birdofpreyru avatar Jan 09 '23 16:01 birdofpreyru

following :)

jfbourne avatar Jan 11 '23 13:01 jfbourne

diff --git a/node_modules/@react-native-firebase/app-check/android/build.gradle b/node_modules/@react-native-firebase/app-check/android/build.gradle
index f253ca2..4d0480d 100644
--- a/node_modules/@react-native-firebase/app-check/android/build.gradle
+++ b/node_modules/@react-native-firebase/app-check/android/build.gradle
@@ -89,7 +89,7 @@ repositories {
 dependencies {
   api appProject
   implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion('firebase', 'bom')}")
-  implementation "com.google.firebase:firebase-appcheck-safetynet"
+  implementation 'com.google.firebase:firebase-appcheck-playintegrity'
   implementation "com.google.firebase:firebase-appcheck-debug"
 }

diff --git a/node_modules/@react-native-firebase/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java b/node_modules/@react-native-firebase/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java
index 676d555..4e0f8b5 100644
--- a/node_modules/@react-native-firebase/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java
+++ b/node_modules/@react-native-firebase/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java
@@ -26,7 +26,7 @@ import com.google.firebase.FirebaseApp;
 import com.google.firebase.appcheck.AppCheckProviderFactory;
 import com.google.firebase.appcheck.FirebaseAppCheck;
 import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory;
-import com.google.firebase.appcheck.safetynet.SafetyNetAppCheckProviderFactory;
+import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory;
 import io.invertase.firebase.common.ReactNativeFirebaseModule;
 import java.lang.reflect.*;

@@ -75,7 +75,7 @@ public class ReactNativeFirebaseAppCheckModule extends ReactNativeFirebaseModule

       } else {
         firebaseAppCheck.installAppCheckProviderFactory(
-            SafetyNetAppCheckProviderFactory.getInstance());
+          PlayIntegrityAppCheckProviderFactory.getInstance());
       }
     } catch (Exception e) {
       rejectPromiseWithCodeAndMessage(promise, "unknown", "internal-error", "unimplemented");

Install yarn add patch-package and create a folder named patches in project root and create a file named @react-native-firebase+app-check+16.5.0.patch and paste all the above code there. and run npx patch-package.

And follow setup instructions(Only step 1) here

BTW one pull request is already open but not yet merged. https://github.com/invertase/react-native-firebase/pull/6401

sanketkheni01 avatar Jan 13 '23 07:01 sanketkheni01

Just tried your solution but got > [appCheck/token-error] com.google.firebase.FirebaseException: No AppCheckProvider installed. Any idea where that is coming from?

grinono avatar Jan 17 '23 11:01 grinono

Just tried your solution but got > [appCheck/token-error] com.google.firebase.FirebaseException: No AppCheckProvider installed. Any idea where that is coming from?

calling .activate() method?

If not, then here is a hook which I created; just call this hook at the root of your project.

import {firebase} from '@react-native-firebase/app-check'
import {useEffect} from 'react'

const useAppCheck = () => {
  useEffect(() => {
    firebase
      .appCheck()
      .activate('ignore', true)
      .then(r => {
        console.log(r)
      })
  }, [])
}

export default useAppCheck

sanketkheni01 avatar Jan 17 '23 11:01 sanketkheni01

@sanketkheni01 i see it's or .activate('ignore', true) or the .getToken() method. I'm looking for the token to validate against a custom backend. after some more setup i now got

[appCheck/token-error] com.google.firebase.FirebaseException: Too many attempts.

for

await firebase.appCheck().getToken();

looks like it's related to > https://github.com/invertase/react-native-firebase/issues/6753

grinono avatar Jan 17 '23 11:01 grinono

Please see the updated app-check docs on rnfirebase.io once the related PR is released (should be in a few minutes, I just merged it)

The key idea in the PR is that everyone wants a firebase-js-sdk compatible API (it is the best way to go, let's admit...) and we want unified behavior on all platforms (app-check has very different behavior across platforms at the native level). There is only one way to do that, and it is with a custom provider that acts as a facade to the underlying native providers.

So to use the Android Play Integrity provider (as well as iOS App Attest if you want...) and unify everything we have a new ReactNativeFirebaseCustomProvider for appcheck which you get, configure with some simple options, then use in the new initializeAppCheck API, and everything should work?

There is a lot of new code under the covers, which means there will inevitably be errors (apologies in advance). I'll be standing by to code up fixes + release them if anyone sees anything.

Cheers

mikehardy avatar Feb 02 '23 17:02 mikehardy

Just checked the code > when i run >

    const appCheckForDefaultApp1 = firebase.appCheck().initializeAppCheck(
      {
        provider: {
          configure: (config) => {
            return {
              provider: 'playIntegrity',
            };
          },
        },
        isTokenAutoRefreshEnabled: true,
      },
    );

i got >

ApolloError: undefined is not an object (evaluating 'options.provider.providerOptions.android')

any idea?

grinono avatar Feb 03 '23 11:02 grinono

@grinono

The config object has one provider sub-property for each platform, so it needs to be nested one deeper than you've done. You need to have the provider/playIntegrity block inside and android block. (you should also have an apple block with either deviceCheck or appAttestWithDeviceCheckFallback (or just appAttest if you have iOS14 as a minimum deploy target on your app)

I believe the example in the documentation shows the nesting with platform-specific providers I describe here?

https://rnfirebase.io/app-check/usage#configure-a-custom-provider

mikehardy avatar Feb 03 '23 13:02 mikehardy

aaah yes missed the android object on restructuring the code but returns the same result.

await firebase.appCheck().initializeAppCheck(
      {
        provider: {
          configure: () => {
            return {
              android: {
                provider: 'playIntegrity',
              },
              // apple: {
              //   provider: 'appAttestWithDeviceCheckFallback',
              // },
              // web: {
              //   provider: 'reCaptchaV3',
              //   siteKey: 'unknown',
              // },
            };
          },
        },
        isTokenAutoRefreshEnabled: true,
      },
    );

result >

ApolloError: undefined is not an object (evaluating 'options.provider.providerOptions.android')

I checked the code but no function with .newReactNativeFirebaseAppCheckProvider(); exists. that is for > "@react-native-firebase/app-check": "^17.0.0",

grinono avatar Feb 03 '23 13:02 grinono

@grinono

I checked the code but no function with .newReactNativeFirebaseAppCheckProvider(); exists. that is for > "@react-native-firebase/app-check": "^17.0.0",

And yet it exists and I exercise it in our e2e suite quite a bit?

https://github.com/invertase/react-native-firebase/blob/53a436278f3c4cb23e1ddb7d2c9f14a65ce4abc1/packages/app-check/lib/index.js#L43-L45

🤔 perhaps this is a typescript issue - appears I've overlooked adding it to the typescript definition file so it is there in javascript but not in typescript. Can't wait until we are typescript native so 🤦 oversights like that don't happen. I'll fix that up but in the meantime can you confirm if you are using it in typescript or not? If you are and that's the problem you can reach in to the node_modules/@react-native-firebase/app-check area and add a quick type definition for that function. Takes no params, returns ReactNativeFirebaseAppCheckProvider - super-standard/easy API to define

mikehardy avatar Feb 03 '23 13:02 mikehardy

ok, resolved it for now with // @ts-ignore

Then i was able to follow the docs page.

    // @ts-ignore
    const provider = firebase.appCheck().newReactNativeFirebaseAppCheckProvider();
    provider.configure({
      android: {
        provider: 'playIntegrity',
      }
    });

    await firebase.appCheck().initializeAppCheck({
      provider: provider,
      isTokenAutoRefreshEnabled: true, 
    });

    const tokenFB = await firebase.appCheck().getToken();
    console.log('tokenRC:', tokenFB);

but it now returns

 [appCheck/token-error] com.google.firebase.FirebaseException: Error returned from API. code: 403 body: App attestation failed.

that is for development on a real device, I tried to run adb logcat | grep DebugAppCheckProvider but this never returns a token to configure.

any idea about this error?

CHATGPT info >

"403 body: App attestation failed." is an error message from Firebase indicating that an application failed to complete the App Attestation process, which is a security feature that helps protect the data stored in Firebase. This error occurs when the app is unable to prove that it has not been tampered with. This can be due to a number of factors such as issues with the Firebase SDK, outdated dependencies, or an attempt to use a cached instance of the Firebase client. To resolve this issue, you may need to update the Firebase SDK and dependencies, or reinitialize the Firebase client.

grinono avatar Feb 03 '23 14:02 grinono