Why the firebase auth StreamBuilder navigate to the HomePage only when an existing user login, but doesn't navigate when a new user sign up in the app - flutter

I have the following:
`
StreamBuilder<User?>(
stream: FirebaseAuth.instance.idTokenChanges(),
builder: (context, AsyncSnapshot<User?> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final User? user = snapshot.data;
if (user == null) {
return Login();
}
return HomePage();
}
return Login();
},
);
**Problem:** when try to login with an existing user email and password, the stream builder move me to theHomePagenormall as expected, but when I try to sign up with a new user email and password, it created fine in the firebase console, but the screen doesn't change to theHomePage`.
when I debug to what happens, after I sign up, the ``useris not null as you see here:
but it just don't open the HomePage.
any ideas, or I'm missing something ?
I'm expecting that if the user login or sign up, the HomePage should opens.
and I want to know why the login works fine, but signing up just don't do nothing

Where did you print "user is not null as you see here:"?
Are you sure the Stream event gets triggered?
If not after user registered try to add this line and see if Stream gets triggered!
await user.reload();

Related

How to keep a user logged in Flutter web app using Firebase Authentication

I am developing a FLutter web app and using Firebase Authentication with email and password login for signing in users
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
After Successfully signing in, the code redirects the user to a HomePage.
Navigator.of(context).pushReplacementNamed('/HomePage');
But when the user refreshes the web page or tries to go to the website again, it has signed out and has to log in again.
Following is the code I use to check the logged in user
StreamBuilder<User?>(
stream: FirebaseAuth.instance.userChanges(),
initialData: FirebaseAuth.instance.currentUser,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null){
Navigator.of(context).pushReplacementNamed('/HomePage');
}else{
Navigator.of(context).pushReplacementNamed('/signup');
}
}
How can I keep the user logged in as long as they use log out?
I want the solution to work specifically on flutter web.
whatever you are building flutter app, web or desktop. you need to keep recorder of user in share preference. this package shared_preferences: ^2.0.15 support web app too. when user will logout then you must need to remove saved data.
Click here:
You should navigate to signup when data is null and to home otherwise but you are doing it reverse.
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null){
Navigator.of(context).pushReplacementNamed('/signup');
}else{
Navigator.of(context).pushReplacementNamed('/Homepage');
}
}

How can you listen to user's email being verified?

When a user signs up they are forced to verify their email. This works but I want the user to be automatically led to the next page if they successfully verify their email. I implemented a StreamBuilder with the userChanges() function.
#override
Widget build(BuildContext context){
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.userChanges(),
builder: (BuildContext context, AsyncSnapshot<User?> snapshot){
if(snapshot.data == null){
return const SignupPage();
}else
if(snapshot.data!.emailVerified){
return const HomePage();
}
return const WaitingText();
},
);
}
Now when the user verifies their mail the page doesn't get updated, but when I force a reload with currenUser.reload() it works.
Is a StreamBuilder the way to go here? I don't want to constantly reload my user until they verify.
This sounds like the expected behavior: the userChanges() stream fires an event when any property of the user changes, but there is no immediate propagation of the server-side change to the client.
This means the verification is only picked up in your client when you re-authenticate the user (i.e. sign-out and sign in again) or when you force the SDK to reload the user profile.

Firebase Authorization is not checking if the user is logged in properly

in my flutter app I want to check if a user is logged in before or not and based on this navigate them to either HomePage or SignIn page. The code I am using is not working fine, it is not navigating to the SignIn page after I've done registration and deleted the account in Firebase Console. In short, when I delete a user, who registered well before, in Firebase Console the application is keeping to show the HomePage and all the posts the user made. How can I handle it?
"In short, I want to navigate the user to SignIn page after I delete his account in Firebase Console"
Here is the code in my main.dart file:
_check(){
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = auth.currentUser;
if(user == null){
HiveDB.deleteUser();
return SignInPage();
}
HiveDB.putUser(id: user.uid);
return HomePage();
}
#override
void initState() {
// TODO: implement initState
super.initState();
_check();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: _check(),
routes: {
SignInPage.id:(context) => SignInPage(),
SignUpPage.id:(context) => SignUpPage(),
HomePage.id:(context) => HomePage(),
},
);
}
The _check() function is not working as it's desired...
While Firebase persists the user info in local storage and automatically restores it when the app/page reloads, this requires that it makes an asynchronous call to the server and thus may not be ready by the time your check runs.
Instead of depending on currentUser, you'll want to listen for changes to the authentication state through the authStateChanges stream. Most apps wrap this in a StreamBuilder and then show the correct screen based on the stream state and last event.
This is something that can be resolved by using async . the problem is you are getting response in future but the action is performed before. Please check the following documentation for detailed overview:
https://dart.dev/codelabs/async-await

Consumer that checks authentication state breaks when navigating to other screens

Users of my app need to authenticate. The authentication state is tracked by a provider class. The login functionality works fine, however, users can also logout, and that is giving problems.
In main.dart I use a consumer widget to track the authentication state:
child: Consumer<AuthenticationProvider>(
builder: (ctx, auth, child) => MaterialApp(
title: 'FlutterChat',
home: auth.isAuth
? WelcomeScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthFlowScreen(),
),
),
),
At app start, the consumer will check the authentication state, if the user is not authenticated, then the user will be redirected to AuthFlowScreen, else the user will see the WelcomeScreen. If the user followed the AuthFlowScreen and successfully authenticates, the user will automatically go to the WelcomeScreen, because that is what the Consumer does.
The WelcomeScreen has a NavBar from which the user can navigate to other parts of the app. The NavBar also has a button to Logout. When this is pressed, the consumer in the main.dart file needs to react. As long as the user didn't navigate to any other screen, the logout works and the AuthFlowScreen is shown to the user. However, if the user navigated to other parts in the app, this does not happen.
Navigation happens with:
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ChatOverviewScreen();
}))
Logout script:
void logout() {
_auth.signOut();
_userEmail = null;
_userId = null;
notifyListeners();
}
It seems that the navigation is messing up the consumer in the main.dart file, however, how can I navigate through the app, such that the consumer in main.dart is still working.
for login system better to use bloc state management, you can find full example here :
https://bloclibrary.dev/#/flutterlogintutorial

How to properly implement Logout with firebase on flutter

It sounds stupid but I cant really properly logout of my app and that is because I use multiple FirebaseAnimatedList and route on my MaterialApp
routes: <String,WidgetBuilder>{
'/StartAppPage':(BuildContext context)=>new StartAppPage(),
'/LoginPage':(BuildContext context)=> new LoginPage(),
'/HomePage':(BuildContext context)=> new HomePage)
},
So the app checks for use and routes to HomePage or Login based on is there is a user or not.
My Home page has a FirebaseAnimatedList and
on my Home page there is a Logout button that do this
await googleSignIn.signOut();
await FirebaseAuth.instance.signOut();
await FirebaseDatabase.instance.goOffline();
return Navigator.pushReplacementNamed(context, '/StartApp');
to HomePage and logout the user.
But when the other user login again the List shows data of the old user and the list is usable messing my Database
How can I properly implement this and the setPersistance is off or on makes no difference
Solution: Keep a single instance of your firebase user through the app. I recommend a global variable
After signing out, what you can consider doing here is check on the current screen if the user is authenticated or not. If the user is still logged-in, display the data. If not, then navigate to a Login screen.
FirebaseAuth.instance
.idTokenChanges()
.listen((User? user) {
if (user == null) {
debugPrint('User is currently signed out!');
// TODO: navigate to Login screen?
} else {
debugPrint('User is signed in!');
// TODO: display data
}
});