Route Guards in Angular

Raghuvardhan Karanam
4 min readOct 21, 2023

--

In any web application, security is very important. One of the ways Angular helps you secure your application is through route guards. Route guards control whether a user can navigate to or away from a particular route. If you've ever been prompted to save changes before leaving a page or been restricted from accessing an admin page, then you've encountered guards.

In this blog post, we will discuss different types of guards, and how to use them effectively in Angular applications along with use cases.

A mind map mentioning different types of angular route gaurds along with an image of angular icon to the right.

What is a Guard?

Think of a guard as a security checkpoint in an airport. It either allows or denies access based on certain conditions. In Angular, a guard is essentially a script that runs before certain stages of route navigation. It decides whether to proceed with the navigation or redirect it. The primary types of guards in Angular are:

  • CanActivate
  • CanActivateChild
  • CanDeactivate
  • Resolve
  • CanLoad

CanActivate

The CanActivate guard checks whether a route can be activated. This is useful for protecting routes that should not be accessible unless certain conditions are met, like user authentication.

Use Case: User Authentication

Imagine you have an admin dashboard that should only be accessible to authenticated users. A CanActivate guard can check if the user is logged in before navigating to the admin page. If the user is not authenticated, the guard redirects them to a login page.

Creating a CanActivate Guard

To create a guard using Angular CLI, you can run:

ng generate guard auth

And implement CanActivate:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {

constructor(private router: Router) {}

canActivate(): boolean {
if (/* your authentication condition */) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}

Adding CanActivate to Routes

Once the guard is ready, add it to the routes you want to protect:

import { AuthGuard } from './auth.guard';

const routes: Routes = [
{ path: 'protected', component: ProtectedComponent, canActivate: [AuthGuard] },
// ...
];

CanActivateChild

Similar to CanActivate, but it works on child routes. Useful for feature modules with multiple child routes.

Use Case: Feature Access Control

Suppose your application has a settings page with multiple child routes like “Profile Settings”, “Account Settings”, and “Privacy Settings”. You can use a CanActivateChild guard to ensure that only users with the appropriate permissions can access these child routes.

const childRoutes: Routes = [
{ path: 'child', component: ChildComponent, canActivateChild: [AuthGuard] },
// ...
];

CanDeactivate

This guard works when you're navigating away from a component. It is often used to warn the user about unsaved changes.

Use Case: Unsaved Changes

You have a form page for editing profile information. If a user makes changes but tries to navigate away without saving, a CanDeactivate guard can prompt them to either save the changes or confirm that they want to leave without saving.

export interface CanComponentDeactivate {
canDeactivate: () => boolean;
}

Implement this interface in your component, and you can use it in a CanDeactivate guard.

Resolve

A Resolve guard fetches data before navigation completes. The data can be used to populate route parameters.

Use Case: Data Preloading

In an e-commerce application, you have a product details page. A Resolve guard can pre-fetch the product details before the route is activated, ensuring that the user doesn't see an empty or partially loaded page.

@Injectable({
providedIn: 'root'
})
export class DataResolver implements Resolve<Data> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Data {
// Fetch your data here
}
}

CanLoad

CanLoad checks if a module should be lazy-loaded or not. This is important if you want to prevent unauthorized users from downloading parts of your application.

Use Case: Feature Gating

Your application has a premium feature module that should only be accessible (and thus downloaded) by premium users. A CanLoad guard can prevent unauthorized users from even downloading this module, saving bandwidth and enhancing security.

const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule),
canLoad: [AuthGuard]
},
// ...
];

Registering Guards

To use the guard, you must provide it in your Angular module.

@NgModule({
providers: [AuthGuard],
// ...
})
export class AppModule {}

Guards in Angular provide a robust way to control navigation in your application. With various types of guards available, you can handle a variety of conditions: check user authentication, warn about unsaved changes, or even pre-fetch data before completing navigation. As a developer, understanding guards is key to ensuring both the security and data integrity of the Angular apps.

Hope you enjoyed the reading.

Please feel free to connect with me on karanam raghuvardhan (@urstruly_raghu) / Twitter or linkedin(https://www.linkedin.com/in/raghuvardhan-karanam/)

--

--