I'm building a flutter app with firebase auth dealing with users. My goal is to streamline the user onboarding experience by allowing email sign up and verification without forcing the user to sign out and sign in again to use the full features. Before testing with real users, this is exactly what I had configured but the overwhelming feedback is that it interrupts and may even cause the user to abandon the authentication flow altogether; the app should simply detect this change in verification status without having to log out.
WHAT I'VE TRIED
I'm using the following in main.dart to provide auth state throughout the app:
StreamProvider < FirebaseUser > .value(
value: FirebaseAuth.instance.onAuthStateChanged,
),
I extract it with
user1 = Provider.of<FirebaseUser>(context, listen: true);
in the individual pages and access different properties like user1.isEmailVerified in ternary expressions to determine what is displayed to the user.
I know that onAuthStateChanged doesn't get called for changes in email verification, only for user sign in and sign out as explained in the accepted answer for this question, but I still need to update the user value that determines the UI shown when a user verifies their email. I have chosen to use a button "complete email verification" which will manually trigger the check and reload of the user profile with the new value once verified. This is the code for that button:
() async {
// 1
FirebaseUser user =
await _firebaseAuth.currentUser();
print(user.isEmailVerified); // returns false
// 2
await user.getIdToken();
print(user.isEmailVerified);// returns false
// 3
await user.reload();
print(user.isEmailVerified);// returns false
//4
user = await _firebaseAuth.currentUser();
print(user.isEmailVerified);// this finally returns true
}
where final _firebaseAuth = FirebaseAuth.instance;
I've noticed that calling .currentUser() twice (before and after reload()) is the only way to actually return true for the .isEmailVerified property without logging out and back in. This is an answer I found in this GitHub thread.
If I press the button again, all the print statements above return true.
THE PROBLEM
That's great, but the problem is the user1 variable that stores the FirebaseUser stream does not change or update even after this, so the UI remains the same despite the user email being verified. I know this because I've placed the following checks in the code:
print('this one is from the stream:');
print(user1.isEmailVerified);
It still returns false even when in the button function body, the user.isEmailVerified returns true.
I've tried calling set state within the button like this:
setState(() {user1 = user; });
But it seems that the value of user1 still remains the same and still returns false for the user1.isEmailVerified, even though I'm trying to set it to the new value derived from the button's function!
This is really frustrating as I feel I'm very close but I just don't know how to refresh the value of the user1 (firebase user stream) throughout the app or even just on that one screen. This should be more straightforward.
I've noticed that pressing hot reload after verifying the email and pressing the button above will automatically show the updated .isEmailVerified value throughout the app while debugging on flutter. Is there a way to programmatically trigger the same kind of rebuild that hot reload uses that will also refresh the firebase user stream data WITHOUT having to log out and sign back in? Maybe this is where the answer lies, but I don't know how to proceed with that.
Any help would be appreciated.