4

I know this question has been asked a lot and I have spent a lot of time reading and trying to implement the answers. So I am trying to get the response from isEmailVerified from Firebase Auth to work and it does work but right now it always returns false unless I refresh the app or close it and reopen it. which is obviously a bad user experience. How do I get the response to update without having to close the app.

here is the relevant pieces of code.

 Future<bool> isEmailVerified() async {
    FirebaseUser user = await _auth.currentUser();

    if (user == null) {
      return false;
    } else {
     await user.reload();
     user = await _auth.currentUser();
      return user.isEmailVerified;
    }
  }

main.dart

  child: Consumer<Auth>(
        builder: (_, auth, __) => MaterialApp(
          theme: Provider.of<ThemeNotifier>(context).getTheme(),
          home: FutureBuilder(
            future: Future.wait([auth.isEmailVerified(), auth.tryAutoLogin()]),
            builder: (BuildContext ctx, AsyncSnapshot authResultSnapshot) =>
                authResultSnapshot.connectionState == ConnectionState.done
                    ? authResultSnapshot.data[1]
                        ? authResultSnapshot.data[0]
                            ? HearingsScreen()
                            : SplashScreen(
                                emailVerified: true,
                              )
                        : LoginScreen()
                    : SplashScreen(),
          ),

It is not returning true until I restart the app
Things I have tried besides this:
1) await user.getIdToken(refresh: true);
2) sign user out then back in
3) firebase_user_stream package

Any help is appreciated.

Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
wcyankees424
  • 2,554
  • 2
  • 12
  • 24

1 Answers1

6

I have implemented the same scenario in a splash screen with below code, you can change it as per your requirement. :

//To check is User is logged in
  Future<bool> isLoggedIn() async {
    FirebaseUser user = await _fireBaseAuth.currentUser();
    if (user == null) {
      return false;
    }
    return user.isEmailVerified;
  }

and

countDownTime() async {
    return Timer(
      Duration(seconds: splashDuration),
      () async {
        if (await userAuth.isLoggedIn()) {
            Navigator.pushReplacement(
              context,
              ScaleRoute(
                widget: HomeScreen(),),
            );
          }
        } else {
          Navigator.pushReplacement(
            context,
            ScaleRoute(
              widget: LoginScreen(),),
          );
        }
      },
    );
  }

and

  @override
  void initState() {
    super.initState();
    countDownTime();
  }

Update
One needs to implement isEmailVerified in initState() function periodically which can be the ideal approach to execute the verification with firebase.

bool _isUserEmailVerified;
Timer _timer;

@override
void initState() {
    super.initState();
    // ... any code here ...
    Future(() async {
        _timer = Timer.periodic(Duration(seconds: 10), (timer) async {
            await FirebaseAuth.instance.currentUser()..reload();
            var user = await FirebaseAuth.instance.currentUser();
            if (user.isEmailVerified) {
                setState((){
                    _isUserEmailVerified = user.isEmailVerified;
                });
                timer.cancel();
            }
        });
    });
}

@override
void dispose() {
    super.dispose();
    if (_timer != null) {
        _timer.cancel();
    }
}
Sanket Vekariya
  • 2,848
  • 3
  • 12
  • 34
  • Do you do an email verification in your app this is the step I am having trouble with in your example all your checking is if the user is not null which does not guarantee ```isEmailVerified``` equals true – wcyankees424 Apr 04 '20 at 19:46
  • you can access by "user.isEmailVerified". – Sanket Vekariya Apr 05 '20 at 02:26
  • I guess you do not need to create new user instance in else part. The same instance defined before is sufficient to know "user.isEmailVerified". – Sanket Vekariya Apr 05 '20 at 02:36
  • yes I have actually implemented code very similar to this in my app but ```user.isEmailVerified``` always returns false until I close the app and restart it. – wcyankees424 Apr 05 '20 at 02:42
  • Have you tried: setState((){ return user.isEmailVerified; }); – Sanket Vekariya Apr 05 '20 at 02:49
  • ```user.isEmailVerified``` is in my Auth class so i can't call setState but ive called ```notifyListeners();``` – wcyankees424 Apr 05 '20 at 02:58
  • 1
    you should try this: https://stackoverflow.com/a/60471750/6911538 – Sanket Vekariya Apr 05 '20 at 03:16
  • I need to play with it more but it appears to be working the key seems to be to move the call to firebase auth ```user.isEmailVerified``` from my auth class to init state of my splash screen. If you want to take the time to amend your answer I will accept it. – wcyankees424 Apr 05 '20 at 04:23