Flutter error: SafetyNet Attestation fails basic integrity

Viewed 3307

Check with SafetyNet fails with error (below). Instead, the recapcha fires with the browser opening.

If anyone comes across, please help. All the information you need is below.

Authorization code:

  Future<void> _submitPhoneNumber() async {
    String phoneNumber = _phone.toString().trim();
    print(phoneNumber);

    void verificationCompleted(AuthCredential phoneAuthCredential) {
      print('verificationCompleted');
      this._phoneAuthCredential = phoneAuthCredential;
      print(phoneAuthCredential);
    }

    void verificationFailed(FirebaseAuthException error) {
      //exception???
      print(error);
    }

    void codeSent(String verificationId, [int code]) {
      print('codeSent');
    }

    void codeAutoRetrievalTimeout(String verificationId) {
      print('codeAutoRetrievalTimeout');
    }

    await FirebaseAuth.instance.verifyPhoneNumber(
      /// Make sure to prefix with your country code
      phoneNumber: phoneNumber,
      timeout: Duration(milliseconds: 10000),
      verificationCompleted: verificationCompleted,
      verificationFailed: verificationFailed,
      codeSent: codeSent,
      codeAutoRetrievalTimeout: codeAutoRetrievalTimeout,
    );
  }

Error log:

E/zzbf    (32691): SafetyNet Attestation fails basic integrity.
W/ActivityThread(32691): handleWindowVisibility: no activity for token android.os.BinderProxy@8394cf8
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J (greylist,core-platform-api, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J (greylist,core-platform-api, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->allocateInstance(Ljava/lang/Class;)Ljava/lang/Object; (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->peekLong(JZ)J (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->pokeLong(JJZ)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->pokeInt(JIZ)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->peekInt(JZ)I (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->pokeByte(JB)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->peekByte(J)B (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->pokeByteArray(J[BII)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Llibcore/io/Memory;->peekByteArray(J[BII)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->arrayBaseOffset(Ljava/lang/Class;)I (greylist,core-platform-api, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->arrayIndexScale(Ljava/lang/Class;)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J (greylist,core-platform-api, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden field Ljava/nio/Buffer;->address:J (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J (greylist,core-platform-api, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, reflection, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V (greylist, reflection, allowed)
W/zzdk    (32691): keyset not found, will generate a new one
W/zzdk    (32691): java.io.FileNotFoundException: can't read keyset; the pref value GenericIdpKeyset does not exist
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzdo.zzc(com.google.firebase:firebase-auth@@20.0.1:10)
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzdo.zzb(com.google.firebase:firebase-auth@@20.0.1:1)
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzat.zzi(com.google.firebase:firebase-auth@@20.0.1:1)
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzdj.zzi(com.google.firebase:firebase-auth@@20.0.1:1)
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzdj.zzd(com.google.firebase:firebase-auth@@20.0.1:2)
W/zzdk    (32691):  at com.google.firebase.auth.internal.zzk.<init>(com.google.firebase:firebase-auth@@20.0.1:7)
W/zzdk    (32691):  at com.google.firebase.auth.internal.zzk.zza(com.google.firebase:firebase-auth@@20.0.1:3)
W/zzdk    (32691):  at com.google.firebase.auth.internal.RecaptchaActivity.zzd(com.google.firebase:firebase-auth@@20.0.1:9)
W/zzdk    (32691):  at com.google.android.gms.internal.firebase-auth-api.zzth.<init>(com.google.firebase:firebase-auth@@20.0.1:13)
W/zzdk    (32691):  at com.google.firebase.auth.internal.RecaptchaActivity.onResume(com.google.firebase:firebase-auth@@20.0.1:43)
W/zzdk    (32691):  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1446)
W/zzdk    (32691):  at android.app.Activity.performResume(Activity.java:7939)
W/zzdk    (32691):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4195)
W/zzdk    (32691):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4237)
W/zzdk    (32691):  at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
W/zzdk    (32691):  at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
W/zzdk    (32691):  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
W/zzdk    (32691):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
W/zzdk    (32691):  at android.os.Handler.dispatchMessage(Handler.java:107)
W/zzdk    (32691):  at android.os.Looper.loop(Looper.java:214)
W/zzdk    (32691):  at android.app.ActivityThread.main(ActivityThread.java:7356)
W/zzdk    (32691):  at java.lang.reflect.Method.invoke(Native Method)
W/zzdk    (32691):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
W/zzdk    (32691):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)
I/zzjy    (32691): Provider GmsCore_OpenSSL not available
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; (greylist, linking, allowed)
W/tter_mobile_ne(32691): Accessing hidden method Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V (greylist, linking, allowed)
W/System  (32691): Ignoring header X-Firebase-Locale because its value was null.
D/EGL_emulation(32691): eglMakeCurrent: 0xebfd1600: ver 2 0 (tinfo 0xec069f80)
D/EGL_emulation(32691): eglMakeCurrent: 0xebfd1600: ver 2 0 (tinfo 0xec069f80)
W/System  (32691): A resource failed to call end.
D/eglCodecCommon(32691): setVertexArrayObject: set vao to 0 (0) 0 0
D/EGL_emulation(32691): eglCreateContext: 0xebfd1180: maj 2 min 0 rcv 2
D/eglCodecCommon(32691): setVertexArrayObject: set vao to 0 (0) 0 0
D/EGL_emulation(32691): eglCreateContext: 0xebfd13c0: maj 2 min 0 rcv 2
D/HostConnection(32691): HostConnection::get() New Host Connection established 0xe0a62cb0, tid 525
D/HostConnection(32691): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
D/EGL_emulation(32691): eglMakeCurrent: 0xebfd13c0: ver 2 0 (tinfo 0xe0ab5160)
D/BackgroundLocatorPlugin(32691): start locator with Google client
D/eglCodecCommon(32691): setVertexArrayObject: set vao to 0 (0) 0 0
D/EGL_emulation(32691): eglCreateContext: 0xcc797060: maj 2 min 0 rcv 2
D/eglCodecCommon(32691): setVertexArrayObject: set vao to 0 (0) 0 0
D/EGL_emulation(32691): eglCreateContext: 0xcc797120: maj 2 min 0 rcv 2
D/HostConnection(32691): HostConnection::get() New Host Connection established 0xe3f624f0, tid 533
D/HostConnection(32691): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
D/EGL_emulation(32691): eglMakeCurrent: 0xcc797120: ver 2 0 (tinfo 0xc32809e0)
Application finished.
Exited (sigterm)

Flutter Doctor:

[√] Flutter (Channel stable, 2.2.1, on Microsoft Windows [Version 10.0.19042.1052], locale ru-RU)
    • Flutter version 2.2.1 at C:\flutter
    • Framework revision 02c026b03c (2 weeks ago), 2021-05-27 12:24:44 -0700
    • Engine revision 0fdb562ac8
    • Dart version 2.13.1

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at C:\Users\User\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 4.1.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] VS Code (version 1.56.2)
    • VS Code at C:\Users\User\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.23.0

[√] Connected device (3 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86    • Android 10 (API 29) (emulator)
    • Chrome (web)                       • chrome        • web-javascript • Google Chrome 91.0.4472.77
    • Edge (web)                         • edge          • web-javascript • Microsoft Edge 91.0.864.41
  1. In Firebase Console SafetyNet is enabled https://i.imgur.com/gBhzRT9.png
  2. SHA-1 and SHA-256 added
  3. Added to build.gradle implementation "androidx.browser:browser:1.3.0"
  4. Added "Android Device Verification" to Google cloud and configured communication with the Firebase project.
2 Answers

If I understood your question correctly, you are wondering why your browser keeps opening to solve a recapcha before your phone number gets verified?

Now, Firebase has undergone a series of updates, introducing the usage of Google's Safety Net security feature for verifying that a particular authentication request is from an actual mobile phone and not from a bot. With this in mind, using an emulator or a test number is likely to trigger the error your're getting, thereby redirecting you to your browser in order for you to complete the verification process without having to start all over again.

You can refer to this doc for further explanation.

If this answer helps, please be sure to mark it as the right answer so as to help others in need find their way.

Happy Coding!

To use phone number authentication, Firebase must be able to verify that phone number sign-in requests are coming from your app. There are two ways Firebase Authentication accomplishes this:

  • SafetyNet: If a user has a device with Google Play Services installed, and Firebase Authentication can verify the device as legitimate with Android SafetyNet, phone number sign-in can proceed.

  • To enable SafetyNet for use with Firebase Authentication:

    1. In the Google Cloud Console, enable the Android DeviceCheck API for your project. The default Firebase API Key will be used, and needs to be allowed to access the DeviceCheck API.
    2. If you haven't yet specified your app's SHA-256 fingerprint, do so from the Settings Page of the Firebase console. Refer to Authenticating Your Client for details on how to get your app's SHA-256 fingerprint.

Example of how the status of the device running your app could affect the value of ctsProfileMatch and basicIntegrity as shown in Table 1:

enter image description here

Error cases

  • A null result indicates that the call to the service didn't complete successfully.
  • An error parameter in the JWS indicates that an issue occurred, such as a network error or an error that an attacker feigned. Most errors are transient and should be absent if you make another call to the service. You might want to retry a few more times with increasing delays between each retry.
  • If the device is tampered—that is, if basicIntegrity is set to false in the response—the verdict might not contain data about the calling app, such as the apkPackageName and apkCertificateDigestSha256. This occurs when our systems cannot reliably determine the calling app.

What to do when the signed attestation reports an error?

  • Retry. Errors on legitimate devices are temporary and should go away if you make another call to the service.
  • Check that your app doesn't call the API more than 5 times per minute on the affected devices and that your project's API quota hasn't been exhausted yet.
  • Assume that it might be an attacker intentionally triggering an error case to masquerade their activity.

Advice for passing future checks :

  • When present, the ‘advice’ parameter provides information to help explain why the SafetyNet Attestation API sets either ctsProfileMatch or basicIntegrity to false in a particular result. The parameter's value contains a list of strings, such as the ones in the following example:

    {"advice": "LOCK_BOOTLOADER,RESTORE_TO_FACTORY_ROM"}

In your app, you can translate the values in the advice parameter into user-friendly messages to help the user pass future SafetyNet attestations.Also have a look at the various possibilities where you can go wrong which may lead to failure of SafetyNet.

  • In the event that SafetyNet cannot be used, such as when the user does not have Google Play Services support, or when testing your app on an emulator, Firebase Authentication uses a reCAPTCHA verification to complete the phone sign-in flow. If you're testing it on an emulator, you need to include the dependency androidx.browser:browser to make it works.The SHA256 key and android device verification API is for a real device to pass Safetynet check.The reCAPTCHA flow will only be triggered when SafetyNet is unavailable or your device does not pass suspicion checks.The reCAPTCHA challenge can often be completed without the user having to solve anything, thereby redirecting you to your browser in order for you to complete the If it doesn't work.
  • Also have a look at the related GitHub issue. If this doesn’t solve your issue,I recommend you to contact the Google Play team for help. You can reach them from this link here
Related