GoRouter Riverpod Authentication

Photo by Waldemar on Unsplash

GoRouter Riverpod Authentication

Go Router Auth

Read code to understand.

https://github.com/CodeHariK/Hashnode/blob/main/riverpod/gorouterauth/README.md

Overview

1.Look pubspec for all dependencies.

cli command to run build runner

dart run build_runner watch --delete-conflicting-outputs

2.App Structure

Onboard -> Login -> Home

3.Riverpod ProviderContainer

        //ProviderContainer : If you want to use listen to provider without consumer widget,
        // and override specific scope of widget tree
        final container = ProviderContainer();

        //Initiate SharedPreferences Storage
        container.listen(storageProvider, (prev, next) {});

        //Initiate GoRouter Redirection Logic
        container.listen(routerRedirectorProvider, (prev, next) {});

        runApp(
            ProviderScope(
            parent: container,
            child: const MyApp(),
            ),
        );

4.GoRouter

        MaterialApp.router(
            routerConfig: router,
        // Listens to auth and onboarding provider and rebuilds gorouter whenever they change.
        @Riverpod(keepAlive: true)
        Future routerRedirector(RouterRedirectorRef ref) async {
            final onboarded = ref.watch(onboardedProvider);
            final authenticated = ref.watch(authenticationProvider).value ?? false;

            myConfig.value = _generateRoutingConfig(
                authenticated: authenticated,
                onboarded: onboarded,
            );
        }
        final ValueNotifier<RoutingConfig> myConfig = ValueNotifier<RoutingConfig>(
            _generateRoutingConfig(authenticated: false, onboarded: false),
        );
        final GoRouter router = GoRouter.routingConfig(
            navigatorKey: AppRouter.rootNavigatorKey,
            routingConfig: myConfig,
            initialLocation: AppRouter.onboard,
        // If (not Onboarded) : go to onboarding
        // If (onboarded) and (not authenticated) : (go to login) or (else go to home)
        // If (not Authenticated) and (going to one of the auth routes), (let it go)
        // If (not Authenticated) and (not going to one of the auth routes), (redirect to login)
        // If (Authenticated) and (going to one of the auth routes), (redirect to home)
        // If (Authenticated) and (not going to one of the auth routes), (let it go)
        RoutingConfig _generateRoutingConfig({required bool authenticated, required bool onboarded}) {
            return RoutingConfig(
                redirectLimit: 100,
                redirect: (context, state) async {
                debugPrint('-> -> -> ${state.uri}  ${state.isAuth}  auth:$authenticated onboard:$onboarded}');

                if (!onboarded) return AppRouter.onboard;
                if (state.match(AppRouter.onboard)) return authenticated ? AppRouter.home : AppRouter.login;

                if (!authenticated && !state.isAuth) return AppRouter.login;
                if (!authenticated && state.isAuth) return null;
                if (authenticated && state.isAuth) return AppRouter.home;
                if (authenticated && !state.isAuth) return null;

                return null;
                },
                routes: <RouteBase>[
                if (authenticated) ...Home.routes,
                if (!authenticated) ...Auth.routes,
                if (!onboarded) ...Onboard.routes,
                ],
            );
        }