Search code examples
flutterfirebasedartfirebase-authenticationnavigation

Flutter Firebase Auth Redirection Not Working After Login When Previously Logged In and Then Logged Out


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:

  • When the app is launched for the first time, and the user logs in, the redirection works as expected — the user is redirected to the HomePage.
  • After logging out, when I attempt to log in again, the app remains on the LoginPage without redirecting to the HomePage.
  • After performing a hot restart, the redirection works correctly and the user is redirected to the HomePage.
  • Additionally, the login only works once after the hot restart, and subsequent login attempts do not trigger the redirection, leaving the user stuck on the login page.

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:

  • Logging in for the first time works as expected, redirecting to the HomePage.
  • After logging out and trying to log in again, the app stays on the LoginPage and does not redirect to the HomePage.
  • A hot restart fixes the redirection, sending the user to the HomePage.
  • After a hot restart, the app logs the user in only once, and subsequent login attempts do not trigger the redirection, leaving the user stuck on the LoginPage.

here is the link of the repo: https://github.com/julienBelinga/mini-social-app/tree/dev


Solution

  • 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.