I'm working on a Flutter app with Firebase Authentication, and after logging out and trying to log back in, the user remains stuck on the LoginPage until a hot restart, at which point the redirection works correctly.
Problem Description:
My main.dart calls auth.dart home: const AuthPage(),
auth.dart:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:mini_social_app/auth/login_or_register.dart';
import 'package:mini_social_app/pages/home_page.dart';
class AuthPage extends StatelessWidget {
const AuthPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
// when user logged in
if (snapshot.hasData) {
return const HomePage();
}
//when user is logged out
else {
return const LoginOrRegister();
}
},
),
);
}
}
login.dart:
void login(BuildContext context) async {
// display the loading circle
showDialog(
context: context,
builder: (context) => const Center(
child: CircularProgressIndicator(),
),
);
// try sign-in
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: mailController.text,
password: passwordController.text,
);
// pop the loading circle
if (context.mounted) Navigator.of(context).pop();
print('login : sign-in');
} on FirebaseException catch (e) {
// pop the loading circle
Navigator.of(context).pop();
displayErrorMessageToUser(e.code, context);
}
}
Expected Behavior:
After logging in and logging out, the user should be redirected to the HomePage without needing a hot restart.
Current Behavior:
After logging out and attempting to log back in, the app stays on the LoginPage. A hot restart is required to trigger the correct redirection. After the restart, the login works only once, and subsequent attempts keep the user on the LoginPage.
I implemented Firebase Authentication in my Flutter app, using authStateChanges() to handle user login and redirection. I created an AuthPage with a FutureBuilder that listens to the authStateChanges() stream. The app is supposed to redirect to the HomePage if the user is logged in, and to the LoginOrRegister page if the user is logged out.
I tested the app in the following scenarios:
here is the link of the repo: https://github.com/julienBelinga/mini-social-app/tree/dev
Turns out the issue was related to navigation between pages, when navigating between pages (e.g., from HomePage to ProfilePage or UsersPage), new pages were added to the navigation stack. This caused problems after logging out or loggin in, as the previous pages remained in the stack, preventing the correct redirection to the login screen.
Solution Implemented:
Replacing Navigator.pushNamed
with Navigator.pushReplacementNamed
:
The core change was replacing Navigator.pushNamed with Navigator.pushReplacementNamed for navigation between HomePage, ProfilePage, and UsersPage. Why the change? Navigator.pushNamed adds a new page to the navigation stack, which can cause issues when navigating back. On the other hand, Navigator.pushReplacementNamed replaces the current page with the new one, ensuring that the navigation stack is not cluttered with extra pages. This solved the issue of the user being stuck on previous pages after logout. Updating the logout method to reset the stack:
The logout method was updated to use Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false)
after logging out.
What does this do?
This clears the entire navigation stack and redirects the user to the root (AuthPage), ensuring that no previous pages are left behind in the stack. This allows for proper redirection to the login screen after logout.
Handling authentication in AuthPage:
AuthPage continues to use StreamBuilder to listen for changes in the authentication state. It automatically redirects the user to HomePage if they are logged in, or to the login/register page if they are logged out.
Explanation of the navigation stack issue:
Before:
When using Navigator.pushNamed
, each navigation added a new page to the stack. If the user logged out from a page like ProfilePage or UsersPage, the previous pages remained in the stack, and this caused unexpected behavior when attempting to navigate back to the login screen.
After: By using Navigator.pushReplacementNamed, the current page is replaced with the new one, preventing unnecessary pages from accumulating in the stack. This allows for a clean navigation flow and correct redirection after logout.
This solution resolved the issue by managing the navigation stack correctly, ensuring the user is always redirected to the login screen after logout, without unwanted pages remaining in the stack.