Unable to get AppCheck (Debug on Emulator) to work on a Flutter application
Asked Answered
O

3

13

I have a flutter application, adding AppCheck and using Android Emulator to test and debug. I am testing the access of Realtime database. From my Firebase Console, AppCheck shows that all my access are of this type: Unverified: invalid requests. I have followed this: https://firebase.google.com/docs/app-check/android/debug-provider.

my app/build.gradle

dependencies {
    ...
    //implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta02'
    implementation 'com.google.firebase:firebase-appcheck-debug:16.0.0-beta03'
    ...
}

In my main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  // Initialize AppCheck
  await FirebaseAppCheck.instance.activate();
...

In MainActivity.kt, I have the following:

import io.flutter.embedding.android.FlutterActivity
import android.os.Bundle
import android.util.Log
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
//import com.google.firebase.appcheck.safetynet.SafetyNetAppCheckProviderFactory

class MainActivity: FlutterActivity() {
    // For Debug Only. Do not do this for Production
    override fun onCreate(savedInstanceState: Bundle?) {
        FirebaseApp.initializeApp(this)
        Log.e("MainActivity", "onCreate")
        val firebaseAppCheck = FirebaseAppCheck.getInstance()
        firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance())
        super.onCreate(savedInstanceState)
    }
}

From logcat, I can see the following log

com.google.firebase.appcheck.debug.internal.DebugAppCheckProvider: Enter this debug secret into the allow list in the Firebase Console for your project: xxxxxxxxxxxxx

Based on the token, I use managed debug token and set it to a debug token.

Using the AppCheck

Realtime Database only shows unverified requests

I am expecting to see verified requests showing up.

I also use Android Studio profiler to monitor the Network, I can see a request

POST https://firebaseappcheck.googleapis.com/v1beta/projects/<app>/apps/<appid>:exchangeSafetyNetToken?key=<key>

In the payload is a JSON safetynet token.

I get a response of 403.

Note that I have not turn on enforcement on the realtime database.

What am I missing with AppCheck? Am I supposed to see verified request using the emulator or only on real physical device (release mode)?

Oxeyed answered 8/10, 2021 at 15:31 Comment(3)
I have a similar problem. I followed the official flutter page firebase.flutter.dev/docs/app-check/usage but without success – Hindu
Same here. Did you ever get this working with the emulator? – Thaxter
I did have the emulator working with App Check in enforcement mode. Then as I was preparing to deploy my app, it stopped, and now gives the 'Missing or insufficient permissions' message. It still works on a physical Android device. I'm trying to work out what changed. – Milli
P
7

I tried with onCreate but couldn't get it to work.

Using a MethodChannel worked instead πŸŽ‰:

// main.dart

void main() async {
 // ...

 await Firebase.initializeApp();
 await FirebaseAppCheck.instance.activate();

 // FirebaseAppCheck when enforced would block incoming requests from Android emulator and iOS simulator too.
 // This kDebugMode check gets a debug token from FirebaseAppCheck which can then be added on the Firebase
 // console so that the emulator and simulator can be allowed to access to Firestore.
 if (kDebugMode) {
  try {
   const MethodChannel methodChannel = MethodChannel("method-channel");
   await methodChannel.invokeMethod("getFirebaseAppCheckDebugToken");
  } catch (e) {
   print("FirebaseAppCheck debug token error: $e");
  }
 }

 // ...
}
// MainActivity.kt

package com.yourname.applicationname

import android.util.Log
import androidx.annotation.NonNull
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "method-channel").setMethodCallHandler { call, result ->
            if (call.method == "getFirebaseAppCheckDebugToken") {
                FirebaseApp.initializeApp(this)
                Log.d("configureFlutterEngine", "FirebaseApp.initializeApp")

                val firebaseAppCheck = FirebaseAppCheck.getInstance()
                Log.d("configureFlutterEngine", "firebaseAppCheck")
                firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance())
                Log.d("configureFlutterEngine", "installAppCheckProviderFactory")

                result.success("Yay!")
            }
        }
    }
}

Result on every app launch on the Android emulator in Flutter debug mode:

FirebaseAppCheck debug token

Patti answered 12/8, 2022 at 7:17 Comment(3)
I got this to work with a slight modification. In flutter main, I only call FirebaseAppCheck.instance.activate() when not in debug mode. – Six
@Six Hmm interesting but not sure how that works. Have you already "enforce"d AppCheck on the Firebase console? – Patti
I'm using App Check with Cloud Functions and this works for me on Android to get the token, which once added too firebase console works for the cloud functions call. – Six
M
0

I managed to workaround this issue (in debug mode) by adding the following condition:

if (kReleaseMode) {
   await FirebaseAppCheck.instance.activate(); 
}
Milli answered 12/8, 2022 at 13:9 Comment(0)
P
0

To ensure that AppCheck works in your flutter project make sure you have the firebase_app_check package installed. Once you do you can use it as such:

import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:flutter/foundation.dart';

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // AppCheck
  await FirebaseAppCheck.instance.activate(
    androidProvider: kDebugMode ? AndroidProvider.debug : AndroidProvider.playIntegrity
  );

  // The rest of your code
}

Using the ternary operator above allows you to set it and forget it. Just remember to enable Enable App Check enforcement to get things running.

Things to remember:

  • Dependencies. Make sure you have implementation platform('com.google.firebase:firebase-bom:31.2.0') in your dependencies in app/build.gradle file (31.2.0 as of writing). When you have bom installed you don't need to import each firebase service individually. The bom takes care of that for you.

    You can compare bom versions here.

  • AppCheck will only work in release builds. For dev use, there's the debug code. Good thing is you only need to set the debug code for every new install per device. That usually means you can keep creating new builds for as long as you don't uninstall it from your emulator. But it never hurts to remember the first few characters just in case.

  • This may be an isolated case but if appcheck still won't work in prod try installing from Playstore by creating a new release.

  • Importing package:flutter/foundation.dart gives you access to kDebugMode

Phosphorous answered 30/1, 2023 at 14:54 Comment(0)

© 2022 - 2025 β€” McMap. All rights reserved.