Skip to main content

Route Guards

Package: @nauth-toolkit/client-angular

Route guards for protecting routes based on authentication.

Available Guards

GuardTypeDescription
authGuardCanActivateFnRequires authentication
AuthGuardclassClass-based auth guard (NgModule)

Setup

// app.routes.ts
import { Routes } from '@angular/router';
import { authGuard } from '@nauth-toolkit/client-angular';

export const routes: Routes = [
// Public routes
{ path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent },

// Protected routes (authenticated users)
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [authGuard()],
},
{
path: 'profile',
component: ProfileComponent,
canActivate: [authGuard()],
},
];

authGuard

Functional guard factory that redirects unauthenticated users to the configured redirects.sessionExpired route, or /login by default.

Call the Function

authGuard is a factory function that must be called with () to return the guard function:

canActivate: [authGuard()]; //  Correct - calls the factory
canActivate: [authGuard]; // Wrong - passes the factory itself
import { authGuard } from '@nauth-toolkit/client-angular';

const routes: Routes = [
{
path: 'protected',
component: ProtectedComponent,
canActivate: [authGuard()],
},
];

Signature

function authGuard(redirectTo?: string): CanActivateFn
ParameterTypeDescription
redirectTostringOptional path to redirect to when not authenticated. Overrides redirects.sessionExpired for this route only.

Behavior

  1. Checks AuthService.isAuthenticated() synchronously
  2. If authenticated → allows navigation
  3. If not authenticated → redirects to redirectTo if provided, else redirects.sessionExpired from config, else /login

Custom Redirect per Route

Pass an optional redirectTo argument to override the config for a specific route:

const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [authGuard('/admin/login')],
},
];

The optional redirectTo parameter overrides the redirects.sessionExpired config for that specific route. Example: authGuard('/custom-login').

Global Redirect Configuration

Set redirects.sessionExpired in your module config to apply a default redirect to all guards:

NAuthModule.forRoot({
baseUrl: 'https://api.example.com/auth',
tokenDelivery: 'cookies',
redirects: {
sessionExpired: '/login?expired=true',
},
})

Lazy Loading with Guards

const routes: Routes = [
{
path: 'admin',
canActivate: [authGuard()],
loadChildren: () => import('./admin/admin.module').then((m) => m.AdminModule),
},
];

Challenge-Aware Guard

Redirect to appropriate challenge page if user has pending challenge:

export const challengeAwareGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);

// Check if there's a pending challenge
const challenge = auth.getCurrentChallenge();
if (challenge?.challengeName) {
switch (challenge.challengeName) {
case 'VERIFY_EMAIL':
return router.createUrlTree(['/verify-email']);
case 'VERIFY_PHONE':
return router.createUrlTree(['/verify-phone']);
case 'MFA_REQUIRED':
return router.createUrlTree(['/mfa']);
case 'MFA_SETUP_REQUIRED':
return router.createUrlTree(['/mfa-setup']);
case 'FORCE_CHANGE_PASSWORD':
return router.createUrlTree(['/change-password']);
}
}

// No challenge, proceed with normal auth check
if (auth.isAuthenticated()) {
return true;
}

return router.createUrlTree(['/login']);
};