What is a Route Guard in Angular?
What is a Route Guard?
A route guard in Angular controls whether navigation to or from a route should be allowed, blocked, or redirected.
A common example is protecting an Admin page.
User tries /admin
↓
Route Guard executes
↓
Is user logged in?
↓
Yes ─────→ Allow /admin
No ──────→ Redirect /login
Route guards are commonly used for:
- Authentication
- Authorization / role checks
- Preventing access to protected pages
- Preventing users from leaving a page with unsaved changes
- Controlling whether certain routes should be matched or loaded
In modern standalone Angular, functional guards are the preferred style.
Full Simple Sample Program
Let's protect a /dashboard route.
If the user is logged in:
/dashboard → Allowed
If not:
/dashboard → Redirect to /login
auth.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private loggedIn = false;
login(): void {
this.loggedIn = true;
}
logout(): void {
this.loggedIn = false;
}
isLoggedIn(): boolean {
return this.loggedIn;
}
}
auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isLoggedIn()) {
return true;
}
return router.createUrlTree(['/login']);
};
login.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
@Component({
selector: 'app-login',
standalone: true,
template: `
<h2>Login</h2>
<button (click)="login()">
Login
</button>
`
})
export class Login {
constructor(
private authService: AuthService,
private router: Router
) {
}
login(): void {
this.authService.login();
this.router.navigate(['/dashboard']);
}
}
dashboard.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-dashboard',
standalone: true,
template: `
<h2>Dashboard</h2>
<p>Welcome to the protected Dashboard.</p>
`
})
export class Dashboard {
}
app.routes.ts
import { Routes } from '@angular/router';
import { Login } from './login';
import { Dashboard } from './dashboard';
import { authGuard } from './auth.guard';
export const routes: Routes = [
{
path: 'login',
component: Login
},
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
];
app.ts
import { Component } from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [
RouterLink,
RouterOutlet
],
template: `
<h1>My Application</h1>
<nav>
<a routerLink="/login">Login</a> |
<a routerLink="/dashboard">Dashboard</a>
</nav>
<hr>
<router-outlet></router-outlet>
`
})
export class App {
}
app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes)
]
};
Explanation
The important route is:
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
This tells Angular:
Before activating
Dashboard, executeauthGuard.
The guard is:
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isLoggedIn()) {
return true;
}
return router.createUrlTree(['/login']);
};
When User Is Logged In
The guard checks:
authService.isLoggedIn()
If it returns:
true
the guard returns:
return true;
Therefore:
User requests /dashboard
↓
authGuard
↓
isLoggedIn() = true
↓
Guard returns true
↓
Navigation allowed
↓
Dashboard displayed
When User Is Not Logged In
If:
authService.isLoggedIn()
returns false, we return:
return router.createUrlTree(['/login']);
This tells Angular Router to redirect the navigation to /login.
User requests /dashboard
↓
authGuard
↓
isLoggedIn() = false
↓
Return /login UrlTree
↓
Dashboard not activated
↓
Login displayed
What Can a Route Guard Return?
A guard can return values such as:
true
Allow navigation.
false
Block navigation.
Or a redirect:
router.createUrlTree(['/login'])
Angular guards can also work asynchronously using:
Promise
Observable
This is useful when authorization logic depends on asynchronous data.
Important Route Guard Types
Modern Angular Router provides several guard functions.
| Guard | Purpose |
|---|---|
CanActivateFn |
Can the user enter this route? |
CanActivateChildFn |
Can the user enter child routes? |
CanDeactivateFn |
Can the user leave this route? |
CanMatchFn |
Should this route configuration match? |
1. CanActivate
Used to control whether a route can be activated.
Example:
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
Typical use:
Is user authenticated?
Is user authorized?
Does user have required role?
2. CanActivateChild
Protects child routes.
Suppose:
/admin
/admin/users
/admin/reports
/admin/settings
Instead of placing the same guard on every child, you can protect child navigation:
{
path: 'admin',
component: Admin,
canActivateChild: [adminGuard],
children: [
{
path: 'users',
component: Users
},
{
path: 'reports',
component: Reports
}
]
}
Conceptually:
/admin
│
└── adminGuard
│
├── /users
└── /reports
3. CanDeactivate
Controls whether the user can leave a route.
For example, the user is editing:
/products/edit/10
and has unsaved changes.
Then the user clicks Home.
Unsaved changes?
↓
Yes
↓
"Are you sure you want to leave?"
A CanDeactivate guard is useful for:
- Unsaved forms
- Unsaved edits
- Multi-step forms
4. CanMatch
CanMatch determines whether a route should be considered a match.
For example:
{
path: 'admin',
canMatch: [adminGuard],
loadComponent: () =>
import('./admin')
.then(m => m.Admin)
}
It can be useful when route matching depends on conditions such as permissions or feature access.
Old Angular: Class-Based Guards
In older Angular applications, guards were commonly implemented as classes.
For example:
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) {
}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
Then:
{
path: 'dashboard',
component: Dashboard,
canActivate: [AuthGuard]
}
Modern Angular favors functional guards:
export const authGuard: CanActivateFn = () => {
const authService = inject(AuthService);
return authService.isLoggedIn();
};
So remember:
Older Angular
↓
Class-based guard
Modern Angular
↓
Functional guard
Route Guard Is NOT API Security
This is extremely important.
Suppose Angular has:
canActivate: [authGuard]
This protects navigation in the Angular UI, but it does not securely protect your ASP.NET Core Web API.
A knowledgeable user could bypass the Angular application and directly call:
GET /api/admin/users
Therefore:
Angular Route Guard
↓
Controls client-side navigation
ASP.NET Core Authorization
↓
Protects server-side API/resources
For an Angular + ASP.NET Core application, you normally need both:
Browser
↓
Angular
↓
Route Guard
↓
Component
↓
HTTP request
↓
ASP.NET Core Web API
↓
Authentication + Authorization
For example, your Web API might independently require:
[Authorize(Roles = "Admin")]
The Angular guard improves navigation and user experience; the backend remains the authoritative security boundary.
Key Points
- Route guards control Angular Router navigation.
CanActivateFndetermines whether a route can be activated.- A guard can allow navigation:
return true;
- It can block navigation:
return false;
- It can redirect:
return router.createUrlTree(['/login']);
- Modern Angular commonly uses functional guards.
- Common guards include:
CanActivate
CanActivateChild
CanDeactivate
CanMatch
- Route guards are commonly used for authentication and authorization-related navigation.
- A route guard does not replace backend security.
Interview Questions and Answers
1. What is a route guard in Angular?
A route guard controls whether Angular Router should allow, block, or redirect navigation based on application logic such as authentication or authorization.
2. How do you protect a route?
Use canActivate:
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
3. What does returning true from a guard mean?
return true;
It means Angular can continue the navigation.
4. What does returning false mean?
return false;
It cancels the current navigation.
5. How do you redirect an unauthorized user?
A common approach is to return a UrlTree:
return router.createUrlTree(['/login']);
6. What is CanDeactivate used for?
CanDeactivate controls whether the user can leave a route. It is commonly used to warn users about unsaved form changes.
7. What is CanMatch?
CanMatch determines whether Angular Router should consider a particular route configuration as a match.
8. Class-based guard vs functional guard?
Older Angular code commonly used class-based guards:
class AuthGuard implements CanActivate
Modern Angular commonly uses functional guards:
const authGuard: CanActivateFn = ...
9. Does a route guard secure a Web API?
No. A route guard only controls client-side Angular navigation. The Web API must perform its own authentication and authorization.
For example, in ASP.NET Core:
[Authorize]
or:
[Authorize(Roles = "Admin")]
should protect sensitive API endpoints.
Interview-ready answer
A route guard in Angular controls navigation based on conditions such as authentication, authorization, or unsaved changes. For example,
CanActivatecan prevent an unauthenticated user from opening/dashboardand redirect them to/login. Modern Angular commonly uses functional guards such asCanActivateFn,CanDeactivateFn, andCanMatchFn. Route guards protect client-side navigation and do not replace server-side API authorization.