'Redirect user to login form if the user is not logged in

I made a web app and deployed it to firebase. Let's say that the link is https://firebasewebapp. When I open the link the Sign In form shows up but when I open https://firebasewebapp/#/home I get redirected to the home page even if the user is not logged in. Is there a way to redirect the user if it's not logged in? I use Flutter 2.10.3 Stable Channel

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: options),
  );
  runApp(MultiProvider(providers: [
  ], child: const MyApp()));
}


class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Portalul e-Radauti',
      theme: ThemeData(
        primarySwatch: Colors.orange,
        textButtonTheme: TextButtonThemeData(
          style: ButtonStyle(
            backgroundColor:
                MaterialStateColor.resolveWith((states) => Colors.orange),
            foregroundColor:
                MaterialStateColor.resolveWith((states) => Colors.white),
          ),
        ),
      ),
      initialRoute: '/login',
      routes: {
        '/home': (_) => const MyHomePage(),
        '/addcouncilmember': (_) => const LocalCouncilLayout(),
        '/signup': (_) => const SignUp(),
        '/login': (_) => const LogIn(),
        '/addevent': (_) => const AddEventLayout(),
        '/profile': (_) => const Profile(),
      },
      //   home: const MyApp(),
    );
  }
}


Solution 1:[1]

The easiest way to do this would be to use Flutter's Navigator 2.0 or a package which wrap Navigator 2.0's API such as go_router or beamer.

Here's an example of how you can implement this behavior by using go_router:

router.dart

import 'package:go_router/go_router.dart';

import 'app.dart';
import 'redirection/log_in.dart';
import 'redirection/my_home_page.dart';
import 'redirection/sign_up.dart';

GoRouter routerGenerator(LoggedInStateInfo loggedInState) {
  return GoRouter(
    initialLocation: Routes.login,
    refreshListenable: loggedInState,
    redirect: (state) {
      final isOnLogin = state.location == Routes.login;
      final isOnSignUp = state.location == Routes.signup;
      final isLoggedIn = loggedInState.isLoggedIn;

      if (!isOnLogin && !isOnSignUp && !isLoggedIn) return Routes.login;
      if ((isOnLogin || isOnSignUp) && isLoggedIn) return Routes.home;
      return null;
    },
    routes: [
      GoRoute(
        path: Routes.home,
        builder: (_, __) => const MyHomePage(),
      ),
      GoRoute(
        path: Routes.login,
        builder: (_, __) => LogIn(loggedInState),
      ),
      GoRoute(
        path: Routes.signup,
        builder: (_, __) => SignUp(loggedInState),
      ),
    ],
  );
}

abstract class Routes {
  static const home = '/home';
  static const signup = '/signup';
  static const login = '/login';
}

app.dart

import 'package:flutter/material.dart';

import 'router.dart';

class LoggedInStateInfo extends ChangeNotifier {
  bool _isLoggedIn = false;
  bool get isLoggedIn => _isLoggedIn;

  void login() {
    _isLoggedIn = true;
    notifyListeners();
  }
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _loggedInStateInfo = LoggedInStateInfo();

  late final _router = routerGenerator(_loggedInStateInfo);

  @override
  void dispose() {
    _loggedInStateInfo.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      routeInformationParser: _router.routeInformationParser,
      routerDelegate: _router.routerDelegate,
    );
  }
}

With this code you only need to update the value of _isLoggedIn inside the LoggedInStateInfo and notify the listeners to access the HomePage, otherwise you will only have access to the LogIn and SignUp pages even when you manually change the URL.

Bonus

LogIn page code

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import '../app.dart';
import '../router.dart';

class LogIn extends StatelessWidget {
  final LoggedInStateInfo loggedInStateInfo;

  const LogIn(this.loggedInStateInfo, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('LogIn')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              onPressed: loggedInStateInfo.login,
              child: const Text('Log In'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () => context.push(Routes.signup),
              child: const Text('Sign Up'),
            ),
          ],
        ),
      ),
    );
  }
}

SignUp page code

import 'package:flutter/material.dart';

import '../app.dart';

class SignUp extends StatelessWidget {
  final LoggedInStateInfo loggedInStateInfo;

  const SignUp(this.loggedInStateInfo, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SignUp')),
      body: Center(
        child: ElevatedButton(
          onPressed: loggedInStateInfo.login,
          child: const Text('Sign Up'),
        ),
      ),
    );
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Guillaume Roux