What is CanActivate in Angular?
What is CanActivate?
CanActivate is an Angular Router route guard used to determine whether a user is allowed to enter/activate a route.
In modern Angular, this is commonly implemented using the functional guard type:
CanActivateFn
For example, before opening:
/dashboard
Angular can check:
User requests /dashboard
↓
CanActivate guard
↓
Is user authenticated?
/ \
Yes No
↓ ↓
Dashboard Login
A common use case is protecting routes that require login.
Full Simple Sample Program
We'll protect /dashboard.
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>
You are successfully logged in.
</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)
]
};
How Does CanActivate Work?
The important route configuration is:
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
The canActivate array tells Angular:
Before activating the
Dashboardroute, executeauthGuard.
The flow is:
User navigates to /dashboard
↓
Angular finds dashboard route
↓
canActivate: [authGuard]
↓
authGuard executes
↓
Is user logged in?
/ \
Yes No
↓ ↓
return true redirect /login
↓
Dashboard
Understanding CanActivateFn
The guard is declared:
export const authGuard: CanActivateFn =
(route, state) => {
// guard logic
};
CanActivateFn is the type for a functional canActivate guard.
It receives useful information:
(route, state)
route
Contains information about the route being activated.
For example, you can access:
route.params
route.queryParams
route.data
state
Contains information about the router state, including the requested URL.
For example:
state.url
If the user requests:
/products/10
then state.url could be:
/products/10
This is useful when you want to redirect the user back to the original page after login.
What Can CanActivate Return?
A guard can return several types of results.
1. true
return true;
Means:
Allow navigation.
CanActivate
↓
true
↓
Route activated
2. false
return false;
Means:
Cancel the navigation.
CanActivate
↓
false
↓
Navigation cancelled
3. Redirect
A guard can return a redirect such as a UrlTree:
return router.createUrlTree(['/login']);
Means:
/dashboard
↓
Guard
↓
Not logged in
↓
/login
Returning a redirect is generally cleaner than manually calling navigate() and then returning false.
4. Promise
A guard can perform asynchronous logic:
return Promise.resolve(true);
5. Observable
A guard can also return an Observable:
return authService.isAuthenticated$;
This is useful when authentication/authorization state is asynchronous.
CanActivate for Authorization
CanActivate isn't limited to checking whether a user is logged in.
It can also check roles or permissions.
For example:
export const adminGuard: CanActivateFn = () => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.getRole() === 'Admin') {
return true;
}
return router.createUrlTree(['/access-denied']);
};
Route:
{
path: 'admin',
component: Admin,
canActivate: [adminGuard]
}
Flow:
/admin
↓
CanActivate
↓
Is Admin?
/ \
Yes No
↓ ↓
Admin Access Denied
Multiple CanActivate Guards
A route can have multiple guards:
{
path: 'admin',
component: Admin,
canActivate: [
authGuard,
adminGuard
]
}
For example:
/admin
↓
authGuard
↓
Is authenticated?
↓
adminGuard
↓
Has Admin access?
↓
Admin Component
This allows you to separate responsibilities.
For example:
authGuard
↓
Authentication
adminGuard
↓
Authorization
CanActivate with Lazy Loading
CanActivate can also protect a lazy-loaded component.
{
path: 'admin',
canActivate: [authGuard],
loadComponent: () =>
import('./admin')
.then(m => m.Admin)
}
Here:
/admin
↓
canActivate
↓
Allowed?
↓
Admin route activated
For controlling whether a route configuration should match in the first place, Angular also provides CanMatch.
Older Angular: Class-Based CanActivate
Before functional guards became the preferred style, Angular applications commonly used a class implementing the CanActivate interface.
import { Injectable } from '@angular/core';
import {
CanActivate,
Router
} from '@angular/router';
import { AuthService } from './auth.service';
@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;
}
}
Route:
{
path: 'dashboard',
component: Dashboard,
canActivate: [AuthGuard]
}
Modern Angular commonly uses:
export const authGuard: CanActivateFn = () => {
// ...
};
So remember:
Older Angular
↓
class AuthGuard implements CanActivate
Modern Angular
↓
CanActivateFn
↓
Functional Guard
CanActivate vs CanActivateChild
Don't confuse these.
CanActivate
Protects a specific route:
{
path: 'admin',
component: Admin,
canActivate: [authGuard]
}
CanActivateChild
Protects child routes:
{
path: 'admin',
component: Admin,
canActivateChild: [authGuard],
children: [
{
path: 'users',
component: Users
},
{
path: 'reports',
component: Reports
}
]
}
Think:
CanActivate
↓
Can I enter this route?
CanActivateChild
↓
Can I enter its child routes?
Advantages
- Prevents unauthorized navigation in the Angular UI.
- Useful for authentication checks.
- Useful for role/permission checks.
- Can redirect unauthenticated users to Login.
- Supports synchronous and asynchronous checks.
- Can be reused across multiple routes.
- Functional guards work naturally with Angular's
inject()API.
Important Security Point
CanActivate is client-side route protection, not server-side security.
Even if Angular protects:
/admin
a user could attempt to directly call:
GET /api/admin/users
Therefore, your ASP.NET Core API must still enforce authorization:
[Authorize(Roles = "Admin")]
[HttpGet]
public IActionResult GetUsers()
{
// ...
}
Think:
Angular CanActivate
↓
Controls UI navigation
ASP.NET Core [Authorize]
↓
Protects API/resources
You generally need both.
Key Points
CanActivatedetermines whether a route can be activated.- In modern Angular, use:
CanActivateFn
- Configure it using:
canActivate: [authGuard]
true→ allow navigation.false→ cancel navigation.- A
UrlTree/redirect result → redirect to another route. - Guards can also return asynchronous results using
PromiseorObservable. - Common uses are authentication and authorization.
- Modern Angular favors functional guards over older class-based guards.
CanActivatedoes not replace backend authorization.
Interview Questions and Answers
1. What is CanActivate?
CanActivate is an Angular route guard used to determine whether a route can be activated.
2. How do you use CanActivate in modern Angular?
Create a functional guard:
export const authGuard: CanActivateFn = () => {
const authService = inject(AuthService);
return authService.isLoggedIn();
};
Then attach it:
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard]
}
3. What happens when CanActivate returns true?
Angular allows the navigation and activates the route.
4. What happens when it returns false?
Angular cancels the navigation.
5. How do you redirect from a CanActivate guard?
Return a redirect such as a UrlTree:
return router.createUrlTree(['/login']);
6. Can CanActivate perform asynchronous checks?
Yes. Guards can return asynchronous results using a Promise or Observable, which is useful when authentication state must be resolved asynchronously.
7. Can we have multiple CanActivate guards?
Yes:
canActivate: [
authGuard,
adminGuard
]
This is useful for separating authentication and authorization checks.
8. CanActivate vs CanActivateChild?
CanActivate protects a particular route, while CanActivateChild controls access to child routes.
Interview-ready answer
CanActivateis an Angular route guard that determines whether a route can be activated. In modern Angular, it is commonly implemented usingCanActivateFn. The guard can returntrueto allow navigation,falseto cancel it, or a redirect result such as aUrlTreeto send the user to another route. It is commonly used for authentication and authorization checks.