Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 [firebase_ui_auth] Null check operator used on a null value at EmailVerificationController.user(email_verification.dart:68) #9

Open
mfizz1 opened this issue Aug 1, 2023 · 12 comments

Comments

@mfizz1
Copy link

mfizz1 commented Aug 1, 2023

Bug report

Describe the bug
Getting a null check operator error when user registers for the first time and is then sent to email verification screen, waiting to verify their email. When the error occurs I get a varied response from the UI sometimes a blank screen, pressing back brings them back to login screen.

Steps to reproduce

Steps to reproduce the behavior:

  1. Register new account using Firebase UI
  2. Email verification screen shown

Expected behavior

Continue waiting for user to verify email

Sample project

This is what I use for my registration screen:

class LoginScreen extends StatelessWidget {
  const LoginScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Material(
      child: SignInScreen(
        providers: providers,
        actions: [
          ForgotPasswordAction(
            (context, email) {
              Navigator.push(
                context,
                forgotPass(email),
              );
            },
          ),
          AuthStateChangeAction<SignedIn>((context, state) {
            if (state.user!.emailVerified) {
              Navigator.pushReplacementNamed(context, '/admin');
            } else {
              Navigator.push(context, verifyEmail());
            }
          }),
          AuthStateChangeAction<UserCreated>((context, state) {
            Navigator.push(context, verifyEmail());
          })
        ],
      ),
    );
    // );; //signScreen();
  }

    MaterialPageRoute<dynamic> verifyEmail() {
    return MaterialPageRoute(
      builder: (context) => EmailVerificationScreen(
        headerBuilder: headerIcon(Icons.mark_email_unread),
        sideBuilder: sideIcon(Icons.mark_email_unread),
        actions: [
          EmailVerifiedAction(() {
            Navigator.pushReplacementNamed(context, '/login');
          }),
          AuthCancelledAction((context) {
            FirebaseUIAuth.signOut(context: context);
            Navigator.pop(context);
          }),
        ],
      ),
    );
  }

  MaterialPageRoute<dynamic> forgotPass(String? email) {
    return MaterialPageRoute(
      builder: (context) => ForgotPasswordScreen(
        headerBuilder: headerIcon(Icons.lock),
        sideBuilder: sideIcon(Icons.lock),
        email: email,
      ),
    );
  }
}

Additional context

Error Details:

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: Null check operator used on a null value
       at EmailVerificationController.user(email_verification.dart:68)
       at EmailVerificationController.reload(email_verification.dart:82)
       at EmailVerificationController.didChangeAppLifecycleState(email_verification.dart:63)
       at WidgetsBinding.handleAppLifecycleStateChanged(binding.dart:713)
       at ServicesBinding._handleLifecycleMessage(binding.dart:261)
       at BasicMessageChannel.setMessageHandler.<fn>(platform_channel.dart:212)
       at _DefaultBinaryMessenger.setMessageHandler.<fn>(binding.dart:479)

ReferenceQueueDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:442)
       at java.lang.Object.wait(Object.java:568)
       at java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:232)
       at java.lang.Daemons$Daemon.run(Daemons.java:140)
       at java.lang.Thread.run(Thread.java:1012)

OkHttp ConnectionPool:
       at java.lang.Object.wait(Object.java)
       at com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:106)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at java.lang.Thread.run(Thread.java:1012)

pool-7-thread-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at java.lang.Thread.run(Thread.java:1012)

Firebase Background Thread firebase/flutterfire#2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at com.google.firebase.concurrent.b.b(:12)
       at com.google.firebase.concurrent.b.a()
       at com.google.firebase.concurrent.a.run(:4)
       at java.lang.Thread.run(Thread.java:1012)

awaitEvenIfOnMainThread task continuation executor1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at g1.x$a$a.a(:2)
       at g1.d.run(:5)
       at java.lang.Thread.run(Thread.java:1012)

queued-work-looper:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loopOnce(Looper.java:186)
       at android.os.Looper.loop(Looper.java:313)
       at android.os.HandlerThread.run(HandlerThread.java:67)

main:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loopOnce(Looper.java:186)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8757)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

Firebase Background Thread firebase/flutterfire#3:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at com.google.firebase.concurrent.b.b(:12)
       at com.google.firebase.concurrent.b.a()
       at com.google.firebase.concurrent.a.run(:4)
       at java.lang.Thread.run(Thread.java:1012)

DefaultDispatcher-worker-3:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:357)
       at kotlinx.coroutines.scheduling.a$c.l(:23)
       at kotlinx.coroutines.scheduling.a$c.r(:48)
       at kotlinx.coroutines.scheduling.a$c.n(:60)
       at kotlinx.coroutines.scheduling.a$c.run()

com.google.firebase.crashlytics.startup1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at g1.x$a$a.a(:2)
       at g1.d.run(:5)
       at java.lang.Thread.run(Thread.java:1012)

FinalizerWatchdogDaemon:
       at java.lang.Thread.sleep(Thread.java)
       at java.lang.Thread.sleep(Thread.java:450)
       at java.lang.Thread.sleep(Thread.java:355)
       at java.lang.Daemons$FinalizerWatchdogDaemon.sleepForNanos(Daemons.java:438)
       at java.lang.Daemons$FinalizerWatchdogDaemon.waitForProgress(Daemons.java:480)
       at java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:369)
       at java.lang.Daemons$Daemon.run(Daemons.java:140)
       at java.lang.Thread.run(Thread.java:1012)

DefaultDispatcher-worker-2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:357)
       at kotlinx.coroutines.scheduling.a$c.l(:23)
       at kotlinx.coroutines.scheduling.a$c.r(:48)
       at kotlinx.coroutines.scheduling.a$c.n(:60)
       at kotlinx.coroutines.scheduling.a$c.run()

Firebase Background Thread firebase/flutterfire#1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at com.google.firebase.concurrent.b.b(:12)
       at com.google.firebase.concurrent.b.a()
       at com.google.firebase.concurrent.a.run(:4)
       at java.lang.Thread.run(Thread.java:1012)

Crashlytics Exception Handler1:
       at dalvik.system.VMStack.getThreadStackTrace(VMStack.java)
       at java.lang.Thread.getStackTrace(Thread.java:1841)
       at java.lang.Thread.getAllStackTraces(Thread.java:1909)
       at g1.r.y(:16)
       at g1.r.o(:4)
       at g1.r.j(:45)
       at g1.r.d(:44)
       at g1.h0.r(:19)
       at g1.h0.s(:32)
       at g1.n$b.a(:49)
       at g1.n$b.call()
       at g1.k$c.then(:2)
       at com.google.android.gms.tasks.zze.run(:8)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at g1.x$a$a.a(:2)
       at g1.d.run(:5)
       at java.lang.Thread.run(Thread.java:1012)

FinalizerDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:442)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:203)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:224)
       at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:300)
       at java.lang.Daemons$Daemon.run(Daemons.java:140)
       at java.lang.Thread.run(Thread.java:1012)

TokenRefresher:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:335)
       at android.os.Looper.loopOnce(Looper.java:186)
       at android.os.Looper.loop(Looper.java:313)
       at android.os.HandlerThread.run(HandlerThread.java:67)

DefaultDispatcher-worker-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:357)
       at kotlinx.coroutines.scheduling.a$c.l(:23)
       at kotlinx.coroutines.scheduling.a$c.r(:48)
       at kotlinx.coroutines.scheduling.a$c.n(:60)
       at kotlinx.coroutines.scheduling.a$c.run()

Firebase Background Thread #0:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2081)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:433)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1063)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at com.google.firebase.concurrent.b.b(:12)
       at com.google.firebase.concurrent.b.a()
       at com.google.firebase.concurrent.a.run(:4)
       at java.lang.Thread.run(Thread.java:1012)

Okio Watchdog:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:442)
       at java.lang.Object.wait(Object.java:568)
       at com.android.okhttp.okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:313)
       at com.android.okhttp.okio.AsyncTimeout.access$000(AsyncTimeout.java:42)
       at com.android.okhttp.okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:288)

Firebase Blocking Thread firebase/flutterfire#1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:234)
       at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:463)
       at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:361)
       at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:939)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1062)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1123)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
       at com.google.firebase.concurrent.b.b(:12)
       at com.google.firebase.concurrent.b.a()
       at com.google.firebase.concurrent.a.run(:4)
       at java.lang.Thread.run(Thread.java:1012)

Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand
[√] Flutter (Channel stable, 3.10.6, on Microsoft Windows [Version 10.0.22621.1992], locale en-GB)
    • Flutter version 3.10.6 on channel stable at C:\Development\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f468f3366c (3 weeks ago), 2023-07-12 15:19:05 -0700
    • Engine revision cdbeda788a
    • Dart version 3.0.6
    • DevTools version 2.23.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at C:\Development
    • Platform android-33, build-tools 33.0.2
    • ANDROID_HOME = C:\Development
    • ANDROID_SDK_ROOT = C:\Development\tools
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
    • All Android licenses accepted.

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

[√] Android Studio (version 2022.2)
    • 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 17.0.6+0-b2043.56-9586694)

[√] VS Code (version 1.80.0)
    • VS Code at ~\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.68.0

[√] Connected device (3 available)
    • VOG L09 (mobile) • 192.168.1.165:5555 • android-arm64  • Android 10 (API 29)
    • Chrome (web)     • chrome             • web-javascript • Google Chrome 115.0.5790.110
    • Edge (web)       • edge               • web-javascript • Microsoft Edge 115.0.1901.188

[√] Network resources
    • All expected network resources are available.

• No issues found!

Flutter dependencies

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

Click To Expand
PASTE OUTPUT INSIDE HERE

@darshankawar
Copy link

@mfizz1
Thanks for the report. Can you provide your flutter doctor -v and plugin version you are using that is throwing the reported error ?
There was a similar issue fixed earlier this year that you can check and see if it helps in your case or not.

@mfizz1
Copy link
Author

mfizz1 commented Aug 1, 2023

Updated the flutter doctor and plugin is as follows:

firebase_ui_auth:
    dependency: "direct main"
    description:
      name: firebase_ui_auth
      sha256: e439571fcad7ed48450eed8d64c70b93765526b876327055469806a51101eff0
      url: "https://pub.dev"
    source: hosted
    version: "1.6.2"

@mfizz1
Copy link
Author

mfizz1 commented Aug 2, 2023

I have looked at the UserCreated state, but I am not sure how it would help in this case. The user is waiting for the email to be verified, once user has completed this, they move on to the "profile" page. This example is straight from the the docs. I saw last month, someone else raised this as an issue as well but it was closed without a fix firebase/flutterfire#11052

@darshankawar
Copy link

Thanks for the update. I tried with the plugin example running on latest master version, registered new user, received email, verified but when clicked continue, I got dynamic link error, but while waiting to confirm, I didn't the reported error:

Screenshot 2023-08-02 at 3 43 19 PM Screenshot 2023-08-02 at 3 44 17 PM

Are there any exact steps or if you could provide a short video when the error triggers would be good to make this issue actionable.

@mfizz1
Copy link
Author

mfizz1 commented Aug 2, 2023

I suppose the question is, what is the expected behaviour here? Once the user verifies email, should it automatically proceed to the next screen? Or does the user have to sign in again or change resume state?

When you verified email, what happened on screen?

I will try producing the error locally.

@danagbemava-nc
Copy link
Contributor

Hi @mfizz1, have you been able to reproduce this locally? I used the plugin example app to do a registration and I was able to register without any issues.

As to what is supposed to happen when you verify your email, it depends on how you've setup your Auth States but with the plugin example app, you will be redirected to the profile page (and based on what I see in your code sample, the same thing should happen)

@mfizz1
Copy link
Author

mfizz1 commented Aug 4, 2023

This is where it seems to be an issue. Whilst I am able to replicate the issue, in terms of the behaviour, it's not flagging up any issues.

The only way I am able to proceed to the screen after email verification, is to cycle to another app and back into this one. Which triggers something to go to profile page. Otherwise I'm waiting with the circular progress indicator.

I will try again today.

@mfizz1
Copy link
Author

mfizz1 commented Aug 4, 2023

I still haven't managed to produce the null error locally. But I noticed noticed a lot more things. Something to do with resuming from a paused state / cycling back the app. One of the other errors produced was:

════════ Exception caught by foundation library ════════════════════════════════
The following assertion was thrown while dispatching notifications for EmailVerificationController:
setState() called after dispose(): __EmailVerificationScreenContentState#a7daf(lifecycle state: defunct, not mounted)

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.

The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

When the exception was thrown, this was the stack
#0      State.setState.<anonymous closure>
firebase/flutterfire#1      State.setState
firebase/flutterfire#2      __EmailVerificationScreenContentState._sendEmailVerification.<anonymous closure>
firebase/flutterfire#3      ChangeNotifier.notifyListeners
firebase/flutterfire#4      ValueNotifier.value=
firebase/flutterfire#5      EmailVerificationController.reload
<asynchronous suspension>
The EmailVerificationController sending notification was: EmailVerificationController#72e1b(EmailVerificationState.verified)
════════════════════════════════════════════════════════════════════════════════

I am sure it must be related as the user cycles back to and from the app when switching to email client

@darshankawar
Copy link

@mfizz1
I tried again, this time, using the email client and app from same device and switched back and forth while email was being verified, but didn't get the above reported and originally reported error. Upon email verification, the user is taken to profile page as below:

Screenshot 2023-08-07 at 4 58 13 PM

Based on the error report, I am going ahead and labeling for team's attention and input.

/cc @lesnitsky

@mfizz1
Copy link
Author

mfizz1 commented Aug 7, 2023

One thing that definitely isn't happening for me is the automatically proceeding to the next screen until the user cycles the app or signs out or signs in again.

I have had several users reporting the same issue.

@lesnitsky lesnitsky transferred this issue from firebase/flutterfire Aug 18, 2023
@lesnitsky lesnitsky added the auth label Aug 18, 2023
@tahamaddam
Copy link

I am facing the exact issue. After a user registers, they are taken to the Email Verification Screen. The loader runs to instruct the user to click on the link in the verification email. The user does click the link, but no event is fired in the app, and the user never moves past that verification screen until manually signing out and signing in. My StreamBuilder code is as follows:

StreamBuilder<User?>(
        stream: _auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // Loading indicator or splash screen while checking authentication status.
            return const CircularProgressIndicator();
          }

          final user = snapshot.data;

          if (user == null) {
            // User is not signed in, show the SignInScreen().
            return SignInScreen(
              providers: [EmailAuthProvider()],
            );
          } else {
            if (!user.emailVerified) {
              // User is signed in but email is not verified, show EmailVerificationScreen().
              return EmailVerificationScreen(auth: _auth);
            } else {
              // User is signed in and email is verified, show ProfileScreen().
              return const ProfileScreen();
            }
          }
        },
      ),

where final FirebaseAuth _auth = FirebaseAuth.instance;

@mihirnestfuel
Copy link

I am facing the exact issue. After a user registers, they are taken to the Email Verification Screen. The loader runs to instruct the user to click on the link in the verification email. The user does click the link, but no event is fired in the app, and the user never moves past that verification screen until manually signing out and signing in. My StreamBuilder code is as follows:

StreamBuilder<User?>(
        stream: _auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // Loading indicator or splash screen while checking authentication status.
            return const CircularProgressIndicator();
          }

          final user = snapshot.data;

          if (user == null) {
            // User is not signed in, show the SignInScreen().
            return SignInScreen(
              providers: [EmailAuthProvider()],
            );
          } else {
            if (!user.emailVerified) {
              // User is signed in but email is not verified, show EmailVerificationScreen().
              return EmailVerificationScreen(auth: _auth);
            } else {
              // User is signed in and email is verified, show ProfileScreen().
              return const ProfileScreen();
            }
          }
        },
      ),

where final FirebaseAuth _auth = FirebaseAuth.instance;

Hey!

Have you got the solution... I am facing the same problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants