firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.63k stars 3.95k forks source link

🐛 [FIREBASE_APP_CHECK] App Check considers all requests to be malicious #6551

Closed Michael-Eliosov closed 1 year ago

Michael-Eliosov commented 3 years ago

Bug report

Requests don't get verified After I added App Check to my project, instead of getting verified, requests are considered malicious. This happens both in simulators and real devices. The SHA-256 in the App Check is the same as in the project settings.

The console gives this error:

W/StorageUtil(11305): Error getting App Check token; using placeholder token instead. Error: com.google.firebase.FirebaseException: 16:

My main() looks like this:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await FirebaseAppCheck.instance.activate(webRecaptchaSiteKey: 'recaptcha-v3-site-key');
  runApp(App());
}

Flutter doctor

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 2.2.3, on Microsoft Windows [Version 10.0.19041.1052], locale en-US) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.3) [√] Chrome - develop for the web [√] Android Studio (version 4.1.0) [√] Connected device (3 available) • No issues found! ```

Flutter dependencies

Click To Expand ``` Dart SDK 2.13.4 Flutter SDK 2.2.3 test 1.0.0+1 dependencies: - cloud_firestore 2.3.0 [cloud_firestore_platform_interface cloud_firestore_web firebase_core firebase_core_platform_interface flutter meta] - cupertino_icons 1.0.3 - firebase_analytics 8.1.2 [firebase_analytics_platform_interface firebase_analytics_web firebase_core flutter meta] - firebase_app_check 0.0.1+2 [firebase_app_check_platform_interface firebase_app_check_web firebase_core firebase_core_platform_interface flutter] - firebase_auth 2.0.0 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta] - firebase_core 1.3.0 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_database 7.1.1 [firebase_core flutter] - firebase_messaging 10.0.3 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta] - firebase_performance 0.7.0+6 [firebase_core flutter] - firebase_storage 9.0.0 [firebase_core firebase_core_platform_interface firebase_storage_platform_interface firebase_storage_web flutter] - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] - flutter_localizations 0.0.0 [flutter intl characters clock collection meta path typed_data vector_math] - flutter_map 0.13.1 [async collection flutter http intl latlong2 meta positioned_tap_detector_2 proj4dart transparent_image tuple vector_math] - flutter_map_location 0.12.0 [flutter flutter_compass flutter_map geolocator latlong2] - flutter_rating_bar 4.0.0 [flutter] - flutter_signin_button 2.0.0 [flutter font_awesome_flutter] - flutter_svg 0.21.0+1 [flutter meta path_drawing vector_math xml] - fluttertoast 8.0.7 [flutter flutter_web_plugins] - google_fonts 2.1.0 [flutter http path_provider crypto] - google_sign_in 5.0.4 [google_sign_in_platform_interface google_sign_in_web flutter meta] - image_cropper 1.4.1 [flutter] - image_picker 0.8.1+3 [flutter flutter_plugin_android_lifecycle image_picker_for_web image_picker_platform_interface] - location 4.3.0 [flutter location_platform_interface location_web] - location_permissions 4.0.0 [flutter meta] - modal_bottom_sheet 2.0.0 [flutter] - photo_view 0.11.1 [flutter] - splashscreen 1.3.5 [flutter] - table_calendar 3.0.1 [flutter intl simple_gesture_detector] - url_launcher 6.0.9 [flutter meta url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows] dev dependencies: - adobe_xd 2.0.0+1 [collection flutter flutter_svg] - flutter_launcher_icons 0.9.0 [args image path yaml] - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data] transitive dependencies: - archive 3.1.2 [crypto path] - args 2.0.0 - async 2.6.1 [meta collection] - boolean_selector 2.1.0 [source_span string_scanner] - characters 1.1.0 - charcode 1.2.0 - clock 1.1.0 - cloud_firestore_platform_interface 5.2.0 [collection firebase_core flutter meta plugin_platform_interface] - cloud_firestore_web 2.2.0 [cloud_firestore_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js] - collection 1.15.0 - crypto 3.0.1 [collection typed_data] - fake_async 1.2.0 [clock collection] - ffi 1.1.2 - file 6.1.2 [meta path] - firebase 9.0.1 [http http_parser js] - firebase_analytics_platform_interface 2.0.1 [flutter meta] - firebase_analytics_web 0.3.0+1 [firebase firebase_analytics_platform_interface flutter flutter_web_plugins meta] - firebase_app_check_platform_interface 0.0.1+2 [firebase_core flutter meta plugin_platform_interface] - firebase_app_check_web 0.0.1+2 [firebase_app_check_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js] - firebase_auth_platform_interface 5.0.0 [firebase_core flutter meta plugin_platform_interface] - firebase_auth_web 2.0.0 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser intl js meta] - firebase_core_platform_interface 4.0.1 [collection flutter meta plugin_platform_interface] - firebase_core_web 1.1.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta] - firebase_messaging_platform_interface 3.0.2 [firebase_core flutter meta plugin_platform_interface] - firebase_messaging_web 2.0.2 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta] - firebase_storage_platform_interface 3.0.0 [collection firebase_core flutter meta plugin_platform_interface] - firebase_storage_web 2.0.0 [async firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta] - flutter_compass 0.6.1 [flutter] - flutter_plugin_android_lifecycle 2.0.2 [flutter] - flutter_web_plugins 0.0.0 [flutter js characters collection meta typed_data vector_math] - font_awesome_flutter 9.1.0 [flutter] - geolocator 7.2.0+1 [flutter geolocator_platform_interface geolocator_web] - geolocator_platform_interface 2.3.0 [flutter plugin_platform_interface vector_math meta] - geolocator_web 2.0.3 [flutter flutter_web_plugins geolocator_platform_interface] - google_sign_in_platform_interface 2.0.1 [flutter meta quiver] - google_sign_in_web 0.10.0 [google_sign_in_platform_interface flutter flutter_web_plugins meta js] - http 0.13.3 [async http_parser meta path pedantic] - http_parser 4.0.0 [charcode collection source_span string_scanner typed_data] - image 3.0.2 [archive meta xml] - image_picker_for_web 2.0.0 [image_picker_platform_interface meta flutter flutter_web_plugins] - image_picker_platform_interface 2.1.0 [flutter meta http plugin_platform_interface] - intl 0.17.0 [clock path] - js 0.6.3 - latlong2 0.8.0 [intl] - lists 1.0.1 [meta] - location_platform_interface 2.3.0 [flutter meta plugin_platform_interface] - location_web 3.1.1 [flutter flutter_web_plugins http_parser js location_platform_interface meta] - matcher 0.12.10 [stack_trace] - meta 1.3.0 - mgrs_dart 2.0.0 [unicode] - path 1.8.0 - path_drawing 0.5.1 [vector_math meta path_parsing flutter] - path_parsing 0.2.1 [vector_math meta] - path_provider 2.0.2 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows] - path_provider_linux 2.0.0 [path xdg_directories path_provider_platform_interface flutter] - path_provider_macos 2.0.0 [flutter] - path_provider_platform_interface 2.0.1 [flutter meta platform plugin_platform_interface] - path_provider_windows 2.0.1 [path_provider_platform_interface meta path flutter ffi win32] - pedantic 1.11.1 - petitparser 4.1.0 [meta] - platform 3.0.0 - plugin_platform_interface 2.0.0 [meta] - positioned_tap_detector_2 1.0.0 [flutter] - process 4.2.1 [file path platform] - proj4dart 2.0.0 [mgrs_dart wkt_parser meta] - quiver 3.0.1 [matcher] - simple_gesture_detector 0.2.0 [flutter] - sky_engine 0.0.99 - source_span 1.8.1 [collection path term_glyph] - stack_trace 1.10.0 [path] - stream_channel 2.1.0 [async] - string_scanner 1.1.0 [charcode source_span] - term_glyph 1.2.0 - test_api 0.3.0 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher] - transparent_image 2.0.0 - tuple 2.0.0 [quiver] - typed_data 1.3.0 [collection] - unicode 0.3.1 [lists] - url_launcher_linux 2.0.0 [flutter] - url_launcher_macos 2.0.0 [flutter] - url_launcher_platform_interface 2.0.4 [flutter plugin_platform_interface] - url_launcher_web 2.0.1 [flutter flutter_web_plugins meta url_launcher_platform_interface] - url_launcher_windows 2.0.0 [flutter] - vector_math 2.1.0 - win32 2.2.4 [ffi] - wkt_parser 2.0.0 - xdg_directories 0.2.0 [meta path process] - xml 5.1.2 [collection meta petitparser] - yaml 3.1.0 [collection source_span string_scanner] ```

markusaksli-nc commented 3 years ago

Hi @Michael-Eliosov The log you provided seems to be related to the issue but just a warning log. Could you provide the actual error with a stacktrace? Thank you

Michael-Eliosov commented 3 years ago

Sometimes there's a different warning like this:

W/StorageUtil( 3852): Error getting App Check token; using placeholder token instead. Error: com.google.firebase.FirebaseException: Error returned from API. code: 403 body: App attestation failed: (My App ID)

I only get errors if I enforce App Check in the Firebase console, since the request isn't verified. They all look like this:

W/Firestore( 9724): (23.0.1) [Firestore]: Listen for Query(target=Query(…) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}

Or like this (without App Check enforced it works fine):

E/flutter ( 9724): [ERROR:flutter/shell/common/shell.cc(103)] Dart Unhandled Exception: [firebase_storage/unauthenticated] User is unauthenticated. Authenticate and try again., stack trace: #0 MethodChannelReference.getDownloadURL (package:firebase_storage_platform_interface/src/method_channel/method_channel_reference.dart:59:7)

markusaksli-nc commented 3 years ago

Have you overridden the Firebase native SDK version in build.gradle or done any similar native setup?

Michael-Eliosov commented 3 years ago

No.

markusaksli-nc commented 3 years ago

Can't reproduce this but I'll label it for some further investigation

florianh01 commented 3 years ago

Having similar issue, I created an issue on stackoverflow: https://stackoverflow.com/questions/68299859/can-not-generate-a-debug-token-for-firebase-storage-with-app-check

Michael-Eliosov commented 3 years ago

I've gotten a new warning W/PersistentConnection( 5111): pc_0 - Provided app check credentials are invalid. This usually indicates your FirebaseAppCheck was not initialized correctly.

MaciejCaputa commented 3 years ago

I have the same issue, were you able to resolve it?

Michael-Eliosov commented 3 years ago

No. For now I just removed the library from my project

MaciejCaputa commented 3 years ago

@Michael-Eliosov That's how I set up the debug for android in MainActivity.kt Were you doing it the same way?

package pl.matematykagryzie.app

import android.os.Bundle
import android.util.Log

import io.flutter.embedding.android.FlutterActivity

import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory

class MainActivity: FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
        Log.e("MainActivity", "onCreate")
        FirebaseApp.initializeApp(/*context=*/this)
        val firebaseAppCheck = FirebaseAppCheck.getInstance()
        firebaseAppCheck.installAppCheckProviderFactory(
            DebugAppCheckProviderFactory.getInstance())
    }
}
Michael-Eliosov commented 3 years ago

I didn't do any of the debug stuff.

gOzaru commented 3 years ago

Try updating Firebase SDK on build.gradle It works for me. See Project Settings > General > Your Apps > See SDK Instructions.

Michael-Eliosov commented 3 years ago

I updated the google-services, didn't help

gOzaru commented 3 years ago

I updated the google-services, didn't help

Not the google services.json; the Firebase SDK.

florianh01 commented 3 years ago

Try updating Firebase SDK on build.gradle It works for me. See Project Settings > General > Your Apps > See SDK Instructions.

DIid not work for me.

I upgraded build.gradle to classpath 'com.google.gms:google-services:4.3.10'

and

app/build.gradle to implementation platform('com.google.firebase:firebase-bom:28.3.0')

Michael-Eliosov commented 3 years ago

@gOzaru I know, I meant what @florianh01 did

florianh01 commented 3 years ago

See Project Settings > General > Your Apps > See SDK Instructions.

Where does this path belong to?

Michael-Eliosov commented 3 years ago

The firebase console, except it's useless since those are instructions for Android/iOS, not Flutter

florianh01 commented 3 years ago

Try updating Firebase SDK on build.gradle It works for me. See Project Settings > General > Your Apps > See SDK Instructions.

How did you set up your Kotlin MainActivity?

I have a feeling that mine is never executed.

This is how I did it:

import android.os.Bundle
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {

      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        FirebaseApp.initializeApp(/*context=*/ this)
        val firebaseAppCheck = FirebaseAppCheck.getInstance()
        firebaseAppCheck.installAppCheckProviderFactory(
        DebugAppCheckProviderFactory.getInstance())
    }  

}
gOzaru commented 3 years ago

See Project Settings > General > Your Apps > See SDK Instructions.

Where does this path belong to?

Firebase Console > Project Settings

gOzaru commented 3 years ago

How did you set up your Kotlin MainActivity?

I never set up any Kotlin MainActivity. I just followed the FlutterFire > App Check and found out some clue inside stackoverflow.com. They directed me to update the latest Firebase SDK. First you need to write this on Terminal inside Flutter (Visual Code): npm ls @firebase/database

If the result is smaller than @firebase/database@0.10.9, then you need to delete all node_modules folder and package-lock.json inside functions folder, then try install Firebase Admin SDK by writing npm install firebase-admin@">=9.8.0" --save

Michael-Eliosov commented 3 years ago

What does the Admin SDK have to do with this? The problem is present in release versions, which aren't affected by it

gOzaru commented 3 years ago

What does the Admin SDK have to do with this? The problem is present in release versions, which aren't affected by it

That is main requirement to get App Check working with Cloud Function and all other functions within Firebase Admin SDK. You need to do these all:

  1. Check if @firebase/database@0.10.9 exist. If not, delete all node_modules + package-lock.json. Install Firebase Admin SDK.
  2. Update to the latest Firebase SDK in build.gradle
  3. Update to the latest google-service.json

I spent 3 days working all of these in order to make App Check work for all Cloud Functions, Cloud Storage, and its token. Now mine is working and it gets Authenticated => app: valid. auth: valid

gOzaru commented 3 years ago

The firebase console, except it's useless since those are instructions for Android/iOS, not Flutter

It's instructions for Flutter too. I have tested them all.

gulmensedat commented 3 years ago

I was dealing with appcheck issue. Let me share the method I run on my physical device. The issue of upload is important, the method used is important, I will share my own piece of code. Also, I think it is necessary to create a register and token in firebase, which is what I did.

appcheck safety register and manage-debug-tokens https://firebase.flutter.dev/docs/app-check/usage https://firebase.google.com/docs/app-check/manage-debug-tokens.png

my code:

 Future<String> _imageUpload(File imageFile, BuildContext context) async {
    final firebase_storage.FirebaseStorage storage =
        firebase_storage.FirebaseStorage.instance;

    Random rnd = Random();
    final String imgPath =
        'imgs/${rnd.nextInt(4000)}';

    firebase_storage.TaskSnapshot tasking =
        await storage.ref(imgPath).putFile(imageFile);

//alternative 1
    String url = await storage.ref(imgPath).getDownloadURL();
    print('url1 => $url');

//alternative 2
    String url2 = await tasking.ref.getDownloadURL();
    print('url2 => $url2');

    if (url != null) {
      print('uploaded => $url');
      return url;
    }
  }
Michael-Eliosov commented 3 years ago

My app is also registered, debug tokens shouldn't affect release versions. My problems are with downloading data, not uploading it

gulmensedat commented 3 years ago

My app is also registered, debug tokens shouldn't affect release versions. My problems are with downloading data, not uploading it

yes, it's about downloading, it doesn't download on the emulator, but since it downloads on my physical device, I can continue the process. In short, it only works on physical device.

Michael-Eliosov commented 3 years ago

Well, in my case it doesn't work on physical devices either

gulmensedat commented 3 years ago

Well, in my case it doesn't work on physical devices either

Did you follow the steps in the manual? implementation 'com.google.firebase:firebase-appcheck-debug:16.0.0-beta01' ?

Michael-Eliosov commented 3 years ago

No. Why would that matter for a release build on a physical device?

gulmensedat commented 3 years ago

When you add this method to the initstate method, it allows appcheck storage, and the auth problem is gone.

 verify() async {
    await FirebaseAppCheck.instance.activate();
    print(
        'verify status ${FirebaseAppCheck.instance.app.isAutomaticDataCollectionEnabled}');
  }

  @override
  void initState() {
    super.initState();
    verify();
russellwheatley commented 2 years ago

Hey @Michael-Eliosov, did you manage to resolve your problem? I would note that the "error" you printed looks like a warning from a sub dependency (W/StorageUtil(11305)) so not sure if your requests were being blocked.

Michael-Eliosov commented 2 years ago

No. It gives the same error and requests are still invalid even in the release build on physical devices

cyberpwnn commented 2 years ago

Does app check even work?

lokenjon commented 2 years ago

I am going around in circles. I've got 15 tabs open about AppCheck. I cannot test App Check in emulator (android). Some docs state that I need to provide a token for App Check / functions dev work. I am expecting to see something like this in logs: DebugAppCheckProvider: Enter this debug secret into the allow list in the Firebase Console for your project: 123a4567-b89c-12d3-e456-7545445678

In a Flutter environment I have added code to MainActivity.kt. The code is not executed, but does compile. I have added this line to app/build.gradle implementation 'com.google.firebase:firebase-appcheck-debug:16.0.0'

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

class MainActivity: FlutterActivity() { // FirebaseApp.initializeApp(/context=/this) // val firebaseAppCheck = FirebaseAppCheck.getInstance() // firebaseAppCheck.installAppCheckProviderFactory( // DebugAppCheckProviderFactory.getInstance() // ) override fun onCreate(savedInstanceState: Bundle?) { Log.e("MainActivity", "onCreate") FirebaseApp.initializeApp(/context=/ this); val firebaseAppCheck = FirebaseAppCheck.getInstance() firebaseAppCheck.installAppCheckProviderFactory( DebugAppCheckProviderFactory.getInstance()) super.onCreate(savedInstanceState) } }

At the moment I see this exception, but this is probably because I have not provided a debug token? W/FirebaseContextProvider(11693): Error getting App Check token. Error: com.google.firebase.FirebaseException: Too many attempts.

I realize that the AppCheck code may not be stable yet, and changing a lot. Does anyone have a link to an updated list of instructions (end-to-end, with no assumptions made, i.e. permissions?, items that are taken for granted)?

KoheiKanagu commented 2 years ago

~In my case, enabling the Play Integrity API solved the problem on Android.~ ~https://firebase.google.com/docs/app-check/android/play-integrity-provider~

The Play Integrity API may not have had anything to do with it. I enabled SafetyNet in App Check, which may have solved the problem. https://firebase.google.com/docs/app-check/flutter/default-providers#project-setup:~:text=default%20providers%3A%20SafetyNet%20on%20Android

Also, for iOS, DeviceCheck had to be used. App Attest is not supported. https://firebase.google.com/docs/app-check/flutter/default-providers#project-setup:~:text=Device%20Check%20on%20Apple%20platforms

https://github.com/firebase/flutterfire/blob/da36b9861b7d635382705b4893eed85fd672125c/packages/firebase_app_check/firebase_app_check/ios/Classes/FLTFirebaseAppCheckPlugin.m#L111-L125

russellwheatley commented 2 years ago

I've just tested the firebase_app_check example app on android using the debug setup, my requests were being validated. Here is a PR with debug setup that I used to test.

If you're struggling to follow the Firebase android setup, here are the steps I took:

  1. Add these two dependencies to your "android/app/build.gradle".
  2. Add the debug provider to the activate() function in the app-check android plugin code.
  3. Ensure you call FirebaseAppCheck.instance.activate() as early as possible.
  4. Once you run your app, copy the debug token printed in your console, and paste in your Firebase console (Firebase App Check tab) in the "Manage debug tokens".
  5. Make requests (e.g. Firestore database requests) and check in your Firebase App Check tab if the requests were verified.
russellwheatley commented 2 years ago

Hey @kevinthecheung, is there any chance we can update the app check documentation for Flutter?

I have instructions above for android and here for iOS.

Also another open issue for app check debug documentation here

Happy to collaborate if you need further information.

cedvdb commented 1 year ago

Thanks @russellwheatley.

Doesn't this line in your PR add the app check dependency as a project wide dependency ? Eg this is going to be included in the prod build ? Thanks in advance for clarifying, I'm not yet well versed in gradle.

https://github.com/firebase/flutterfire/pull/9412/files#diff-8107edb4682a9ff40bb5fbb2b85c46574366123c1ddb5ebb5b66a4593cf5a708R55

Side note, it seems that this setup is quite different from the setup from the official documentation, which is android specific, as some steps are omitted.