Router Guard
redirect mechanism wired to authStateChanges instead, that's the pattern used throughout the rest of these docs. The widgets on this page are specifically for apps on plain Navigator with named routes.Authyra deliberately doesn't ship a GoRouter-specific guard; router diversity in the Flutter ecosystem (GoRouter, AutoRoute, Beamer, VRouter, Navigator 2.0) means one guard can't fit all of them well, and Authyra's job is the auth logic, not navigation. For Navigator-based apps, these four widgets cover the common cases.
AuthyraGuardConfig
Shared configuration for AuthyraGuard and AuthyraInverseGuard:
class AuthyraGuardConfig {
final String? loginRoute;
final Widget Function(BuildContext)? loginBuilder;
final String? homeRoute;
final Widget Function(BuildContext)? loadingBuilder;
final bool allowOnError;
final Future<bool> Function(AuthSession?)? customCheck;
}
Either loginRoute or loginBuilder is required. customCheck overrides the default "session exists and isn't expired" logic; allowOnError controls whether a thrown error during the check counts as authenticated (default false, denies).
AuthyraGuard
Wrap content that requires authentication:
AuthyraGuard(
config: AuthyraGuardConfig(loginRoute: '/login'),
child: const HomePage(),
)
Shows config.loadingBuilder (or a default spinner) while checking, then either child or navigates to loginRoute/loginBuilder.
AuthyraInverseGuard
The opposite: wrap a login/register page that shouldn't be reachable once signed in:
AuthyraInverseGuard(
config: AuthyraGuardConfig(homeRoute: '/home'),
child: const LoginPage(),
)
AuthyraNavigationObserver
Guards a named list of routes at the Navigator level instead of wrapping each page:
MaterialApp(
navigatorObservers: [
AuthyraNavigationObserver(
loginRoute: '/login',
protectedRoutes: ['/profile', '/settings', '/admin'],
),
],
)
Checks Authyra.instance.isAuthenticated (or your customAuthCheck) on every didPush into a protected route name, and redirects to loginRoute if it fails.
AuthyraRouter
A single top-level split, useful for the simplest apps that just need "logged in screen" vs "logged out screen":
MaterialApp(
home: AuthyraRouter(
authenticatedBuilder: (context) => const HomePage(),
unauthenticatedBuilder: (context) => const LoginPage(),
loadingBuilder: (context) => const SplashScreen(),
),
)
Listens to sessionStream internally and swaps builders reactively.
See also
- Route Protection guide →, full walkthrough including GoRouter
- Reactivity →