firebase / FirebaseUI-Flutter

Apache License 2.0
99 stars 86 forks source link

🐛 [firebase_ui_auth] Login via google after deleting email account triggers error #27

Open Jamie-505 opened 1 year ago

Jamie-505 commented 1 year ago

Bug report

When you delete an email account from the profile page and land back on the sign-in page, choosing sign-in with Google results in nothing happening. But when you reload the app you're signed in.

Error message:

E/flutter (21971): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
E/flutter (21971): #0      EmailVerificationController.user (package:firebase_ui_auth/src/email_verification.dart:68:36)
E/flutter (21971): firebase/flutterfire#1      EmailVerificationController.reload (package:firebase_ui_auth/src/email_verification.dart:82:11)
E/flutter (21971): firebase/flutterfire#2      EmailVerificationController.didChangeAppLifecycleState (package:firebase_ui_auth/src/email_verification.dart:63:7)
E/flutter (21971): firebase/flutterfire#3      WidgetsBinding.handleAppLifecycleStateChanged (package:flutter/src/widgets/binding.dart:673:16)
E/flutter (21971): firebase/flutterfire#4      ServicesBinding._handleLifecycleMessage (package:flutter/src/services/binding.dart:262:5)
E/flutter (21971): firebase/flutterfire#5      BasicMessageChannel.setMessageHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:214:49)
E/flutter (21971): firebase/flutterfire#6      _DefaultBinaryMessenger.setMessageHandler.<anonymous closure> (package:flutter/src/services/binding.dart:393:35)
E/flutter (21971): firebase/flutterfire#7      _invoke2 (dart:ui/hooks.dart:183:13)
E/flutter (21971): firebase/flutterfire#8      _ChannelCallbackRecord.invoke (dart:ui/channel_buffers.dart:40:5)
E/flutter (21971): firebase/flutterfire#9      _Channel.push (dart:ui/channel_buffers.dart:130:31)
E/flutter (21971): firebase/flutterfire#10     ChannelBuffers.push (dart:ui/channel_buffers.dart:326:17)
E/flutter (21971): firebase/flutterfire#11     PlatformDispatcher._dispatchPlatformMessage (dart:ui/platform_dispatcher.dart:664:22)
E/flutter (21971): firebase/flutterfire#12     _dispatchPlatformMessage (dart:ui/hooks.dart:86:31)
E/flutter (21971): 

Steps to reproduce

Steps to reproduce the behavior:

  1. Have your sign-in event trigger redirect to profile page with
    AuthStateChangeAction<SignedIn>((context, state) {
    Navigator.pushReplacementNamed(context, '$profileRoute');
    }),
  2. Have your sign-out action ont the profile screen route back to the sign-in page and delete the stack (to prevent user from going back to previous screens) like:
    ProfileScreen(
    // ... appBar etc.
    actions: [
    SignedOutAction((context) {
      Navigator.pushAndRemoveUntil(context,
        MaterialPageRoute(builder: (BuildContext context) {
          return const SignInScreen();
        }), (r) {
          return false;
        });
    })
    ],
    )
  3. register with email
  4. delete account on profile page (should bring you back to sign-in screen)
  5. click on sign-in with Google and sign-in with Google account
  6. be stuck on sign-in screen (with logs showing the mentioned stacktrace)

Expected behavior

Step 5 in reproduce should redirect to profile page


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.7.10, on macOS 13.3 22E252 darwin-arm64, locale en-DE) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 14.3) [✓] Chrome - develop for the web [!] Android Studio (not installed) [✓] IntelliJ IDEA Ultimate Edition (version 2022.3.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3) [✓] IntelliJ IDEA Ultimate Edition (version 2022.3.1) [✓] VS Code (version 1.74.0) [✓] Connected device (3 available) [✓] HTTP Host Availability ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand ``` Dart SDK 2.19.6 Flutter SDK 3.7.10 butterfly 1.0.0+1 dependencies: - firebase_auth 4.4.0 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta] - firebase_core 2.9.0 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_database 10.1.0 [firebase_core firebase_core_platform_interface firebase_database_platform_interface firebase_database_web flutter] - firebase_dynamic_links 5.1.0 [firebase_core firebase_core_platform_interface firebase_dynamic_links_platform_interface flutter meta plugin_platform_interface] - firebase_ui_auth 1.2.0 [email_validator firebase_auth firebase_core firebase_dynamic_links firebase_ui_localizations firebase_ui_oauth firebase_ui_shared flutter flutter_localizations flutter_svg] - firebase_ui_oauth_google 1.0.21 [firebase_auth firebase_ui_oauth flutter google_sign_in] - flutter 0.0.0 [characters collection js material_color_utilities meta vector_math sky_engine] - google_fonts 4.0.3 [flutter http path_provider crypto] - google_sign_in 5.4.4 [flutter google_sign_in_android google_sign_in_ios google_sign_in_platform_interface google_sign_in_web] - intl 0.17.0 [clock path] - wear 1.1.0 [flutter] dev dependencies: - flutter_lints 2.0.1 [lints] - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters collection js matcher material_color_utilities meta source_span stream_channel string_scanner term_glyph] transitive dependencies: - _flutterfire_internals 1.1.0 [collection firebase_core firebase_core_platform_interface flutter meta] - async 2.10.0 [collection meta] - boolean_selector 2.1.1 [source_span string_scanner] - characters 1.2.1 - clock 1.1.1 - collection 1.17.0 - crypto 3.0.2 [typed_data] - desktop_webview_auth 0.0.11 [crypto flutter http flutter_web_plugins plugin_platform_interface] - email_validator 2.1.17 - fake_async 1.3.1 [clock collection] - ffi 2.0.1 - file 6.1.4 [meta path] - firebase_auth_platform_interface 6.13.0 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface] - firebase_auth_web 5.3.0 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser intl js meta] - firebase_core_platform_interface 4.6.0 [collection flutter flutter_test meta plugin_platform_interface] - firebase_core_web 2.3.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta] - firebase_database_platform_interface 0.2.3 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface] - firebase_database_web 0.2.2 [firebase_core firebase_core_web firebase_database_platform_interface flutter flutter_web_plugins js] - firebase_dynamic_links_platform_interface 0.2.4 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface] - firebase_ui_localizations 1.3.0 [flutter flutter_localizations intl path] - firebase_ui_oauth 1.2.0 [desktop_webview_auth firebase_auth firebase_ui_auth firebase_ui_shared flutter_svg flutter] - firebase_ui_shared 1.1.0 [flutter] - flutter_localizations 0.0.0 [flutter intl characters clock collection js material_color_utilities meta path vector_math] - flutter_svg 1.1.6 [flutter meta path_drawing vector_math xml] - flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta vector_math] - google_sign_in_android 6.1.8 [flutter google_sign_in_platform_interface] - google_sign_in_ios 5.6.1 [flutter google_sign_in_platform_interface] - google_sign_in_platform_interface 2.4.0 [flutter plugin_platform_interface quiver] - google_sign_in_web 0.10.2+1 [flutter flutter_web_plugins google_sign_in_platform_interface js] - http 0.13.5 [async http_parser meta path] - http_parser 4.0.2 [collection source_span string_scanner typed_data] - js 0.6.5 [meta] - lints 2.0.1 - matcher 0.12.13 [meta stack_trace] - material_color_utilities 0.2.0 - meta 1.8.0 - path 1.8.2 - path_drawing 1.0.1 [vector_math meta path_parsing flutter] - path_parsing 1.0.1 [vector_math meta] - path_provider 2.0.14 [flutter path_provider_android path_provider_foundation path_provider_linux path_provider_platform_interface path_provider_windows] - path_provider_android 2.0.24 [flutter path_provider_platform_interface] - path_provider_foundation 2.2.1 [flutter path_provider_platform_interface] - path_provider_linux 2.1.10 [ffi flutter path path_provider_platform_interface xdg_directories] - path_provider_platform_interface 2.0.6 [flutter platform plugin_platform_interface] - path_provider_windows 2.1.5 [ffi flutter path path_provider_platform_interface win32] - petitparser 5.1.0 [meta] - platform 3.1.0 - plugin_platform_interface 2.1.4 [meta] - process 4.2.4 [file path platform] - quiver 3.2.1 [matcher] - sky_engine 0.0.99 - source_span 1.9.1 [collection path term_glyph] - stack_trace 1.11.0 [path] - stream_channel 2.1.1 [async] - string_scanner 1.2.0 [source_span] - term_glyph 1.2.1 - test_api 0.4.16 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph matcher] - typed_data 1.3.1 [collection] - vector_math 2.1.4 - win32 3.1.3 [ffi] - xdg_directories 1.0.0 [meta path process] - xml 6.2.2 [collection meta petitparser] ```

FMorschel commented 11 months ago

I'm unsure how to solve this, but I just want to put out here what I was having trouble with. Seems to be related.

When you first select an email with the Google Sign-in button, it keeps it cached somewhere and to this moment, I was not able to find any configuration option so that I could potentially log in with a different email. Say I needed to log into another account that also only has Google Sing-in enabled for example.

Only able to clean this cached email by cleaning the app's full data. Not even cache only.

FMorschel commented 11 months ago

Looking inside the package, I found a signInSilently method inside GoogleSignIn. Couldn`t find if it's been called. But that could probably be the issue here. See the docs:

Attempts to sign in a previously authenticated user without interaction.

Returned Future resolves to an instance of [GoogleSignInAccount] for a successful sign in or null if there is no previously authenticated user. Use [signIn] method to trigger interactive sign in process.

Authentication is triggered if there is no currently signed in user (that is when currentUser == null), otherwise this method returns a Future which resolves to the same user instance.

Re-authentication can be triggered after [signOut] or [disconnect]. It can also be triggered by setting [reAuthenticate] to true if a new ID token is required.

When [suppressErrors] is set to false and an error occurred during sign in returned Future completes with [PlatformException] whose code can be one of [kSignInRequiredError] (when there is no authenticated user) , [kNetworkError] (when a network error occurred) or [kSignInFailedError] (when an unknown error occurred).

FMorschel commented 11 months ago

Found a solution. Missing the call to disconnect. I added it inside a FirebaseAuth.instance.authStateChanges().listen call when the user is null at the start of my app. This means that the user has logged out.

I'm currently using:

  final googleProvider = GoogleProvider(clientId: googleClientID);
  FirebaseUIAuth.configureProviders([
    googleProvider,
    PhoneAuthProvider(),
    EmailAuthProvider(),
  ]);
  runApp(MainApp(googleProvider: googleProvider));

I'm not sure if this works in any GoogleProvider or if it has to be the one used. So just be aware of it.