Route Guards in Angular
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.
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/)