简体   繁体   中英

Firebase Functions AppCheck keeps failing my device

I have been trying to integrate AppCheck with my Android app, but I can't seem to make a valid request.

As for test purposes, I have been using the following code:

Android Code

class Application : MultiDexApplication() {

    override fun onCreate() {
        FirebaseApp.initializeApp(this)

        val appCheck = FirebaseAppCheck.getInstance()
        if (BuildConfig.DEBUG) appCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance(), true)
        else appCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance(), true)

        super.onCreate()
    }
}

class TestActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        val data = "This is a test!"
        Firebase.functions.getHttpsCallable("test").call(data).addOnCompleteListener {
            if (it.isSuccessful) {
                val result = it.result.data
                print(result)
            }

            else {
                val exception = it.exception
                print(exception)
            }
        }
    }
}

Function Code

const functions = require("firebase-functions")

exports.test = functions.https.onCall((data, context) => {
  if (context.app == undefined) {
    functions.logger.error("Test - Failed validating device integrity!")
    throw new functions.https.HttpsError("failed-precondition", "The function must be called from an App Check verified app")
  }

  return data
})

I have added the DebugAppCheckProviderFactory token to the Firebase console, but no matter what I do, if it is an emulator or physical device, when I call the function, the failed-precondition exception is always thrown.

Checking the function logs, I can see that the app is missing:

在此处输入图像描述

I have already read the documentation multiple times and I can't seem to be missing any step. Am I missing something or is there anything I can do to find the root cause for this?

Thank you for your time!

EDIT:

As for Martin suggestion, I created a new OnRequest function and added the X-Firebase-AppCheck header. I received the token correctly and was able to validate it successfully with:

firebaseAdmin.appCheck().verifyToken(appCheckToken)

So, my guess is that Android is not adding the X-Firebase-AppCheck automatically to the OnCall function like it should.

I ran the code and made some breakpoints through the code and noticed the following. The call method from Firebase is adding the Firebase-Instance-ID-Token but I can't seem to find the X-Firebase-AppCheck header anywhere. Maybe I am not supposed to see this value, or maybe I just can't find where it is being added. Or maybe it is not added at all, thus I can't validate my context.app at all.

It may be required to obtain an AppCheckToken :

FirebaseAppCheck
        .getInstance()
        .getAppCheckToken(false)
        .addOnSuccessListener(new OnSuccessListener<AppCheckToken>() {
            @Override
            public void onSuccess(@NonNull AppCheckToken tokenResponse) {

                String appCheckToken = tokenResponse.getToken();
                ...
            }
        });

Which has to be passed along, with the HTTP request (the example shows Retrofit, which could also be used instead of HttpsCallable :

@GET("yourExampleEndpoint")
Call<List<String>> exampleData(
    @Header("X-Firebase-AppCheck") String appCheckToken,
    ...
);

Where FirebaseFunctions.getInstance().getHttpsCallable().call() doesn't tell how or if one has to explicitly set that X-Firebase-AppCheck header. Cloud Functions should usually receive an X-Firebase-AppCheck header - with the previously retrieved AppCheck token:

const appCheckToken = req.header('X-Firebase-AppCheck');

if (!appCheckToken) {
    res.status(401);
    return next('Unauthorized');
}

try {
    const appCheckClaims = await firebaseAdmin.appCheck().verifyToken(appCheckToken);
    // If verifyToken() succeeds, continue with the next middleware function in the stack.
    return next();
} catch (err) {
    res.status(401);
    return next('Unauthorized');
}

One can also issue own tokens...and checking for context-app is also valid.


Update: The Protocol specification for https.onCall reads:

Optional: X-Firebase-AppCheck: <token>

The Firebase App Check token provided by the client app making the request. The backend automatically verifies this token and decodes it, injecting the appId in the handler's context. If the token cannot be verified, the request is rejected.

Available for SDK >=3.14.0

To install the minimum required NodeJS dependencies:

npm install firebase-functions@">=3.14.0"
npm install firebase-admin@">=9.8.0"

And last, but not least...there's even a debug helper for that:

dependencies {
    debugImplementation "com.google.firebase:firebase-appcheck-debug:16.0.0-beta02"
}

After testing everything with no success, in a desperate move, I tried to look to unrelated files and found the solution.

In my build.gradle I was importing all the Firebase dependencies with the bom:

implementation platform("com.google.firebase:firebase-bom:27.0.0")
implementation "com.google.firebase:firebase-crashlytics-ktx"
implementation "com.google.firebase:firebase-analytics-ktx"
implementation "com.google.firebase:firebase-firestore-ktx"
implementation "com.google.firebase:firebase-functions-ktx"
implementation "com.google.firebase:firebase-auth-ktx"

So I thought: "Can the firebase-bom be importing an outdated functions-ktx dependency?"

And guess what? As soon as I imported the dependencies without the bom, I started to see the X-Firebase-AppCheck being added and the context.app being valid.

I ended up with the following build.gralde :

implementation "com.google.firebase:firebase-crashlytics-ktx:18.2.1"
implementation "com.google.firebase:firebase-analytics-ktx:19.0.0"
implementation "com.google.firebase:firebase-firestore-ktx:23.0.3"
implementation "com.google.firebase:firebase-functions-ktx:20.0.0"
implementation "com.google.firebase:firebase-auth-ktx:21.0.1"

After a little more investigation, I found out that I was using an outdated firebase-bom version. Android Studio used to let me know if there was a new version for the dependencies, but it did not notice me for the firebase-bom . Turns out, that I just need to update my firebase-bom dependency.

TL;DR

Check your Android Firebase libraries version!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM