☰ See All Chapters |
Angular Routing Security - Route Guards
Angular route guards are the pre navigate process can be used to execute defined actions before activating the route. The Angular supports several guards like CanActivate, CanDeactivate, Resolve, CanLoad, and CanActivateChild. To check whether user is a valid user before allowing him to navigate to secured pages you can use CanActivate.
Uses of Guards
To confirm navigational operation
Asking whether to save before moving away from a view
Allow access to certain parts of the application to specific users
Validating the route parameters before navigating to the route
Fetching some data before you display the component.
Different Route Guards
The Angular Router supports Five different guards, which you can use to protect the route
CanActivate
CanDeactivate
Resolve
CanLoad
CanActivateChild
CanActivate
This guard decides if a route can be activated (or component gets used). This guard is useful in the circumstance where the user is not authorized to navigate to the target component. Or the user might not be logged into the system
CanDeactivate
This Guard decides if the user can leave the component (navigate away from the current route). This route is useful in where the user might have some pending changes, which was not saved. The canDeactivate route allows us to ask user confirmation before leaving the component. You might ask the user if it’s OK to discard pending changes rather than save them.
Resolve
This guard delays the activation of the route until some tasks are completed. You can use the guard to pre-fetch the data from the backend API, before activating the route
CanLoad
This guard is used to guard the routes that load feature modules dynamically
CanActivateChild
This guard determines whether a child route can be activated.
How to Build Angular Route Guards
Build the Guard as Service.
Implement the Guard Method in the Service
Register the Guard Service in the Root Module
Update the Routes to use the guards
Build the Guard as Service
Building the Guard Service is simple as building any other Angular Service. We need to import the corresponding guard from the Angular Router Library using the Import statement. For Example to use CanActivate Guard, import the CanActivate in the import statement.
import { CanActivate } from '@angular/router'; |
Next, create the Guard
@Injectable() export class UserAuthentication implements CanActivate { } |
Class which implements the selected guard Interface as shown below. We can also inject other services into the Guards using the Dependency Injection.
Implement the Guard Method
Implement the respective guard method. For Example to implement the CanActivate guard, create a method CanActivate. This method will take two parameters ActivatedRouteSnapshot and RouterStateSnapshot. And this method should return Boolean value. The parameters and return value depends on the guard Interface we implement.
@Injectable() export class UserAuthentication implements CanActivate { name: string; constructor(private _router:Router ) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { this.name = route.params['name']; if (this.name == 'Manu') { return true; } else { this._router.navigate(["failure",this.name ]); return false; } } } |
The canActivate guard method must return either a true or a false value. If it returns true, the navigation process continues. If it returns false, the navigation process stops and the user stays put. The above method returns a True value, if the user name is “Manu”. The Guard can also return an Observable or a Promise which eventually returns a True or false. The guard can also tell the router to navigate elsewhere, effectively canceling the current navigation.
Register the Guard as Service in Module
As mentioned earlier, guards are nothing but services. Hence they need to be registered with the Providers array of the application Module as shown below.
providers: [UserAuthentication] |
Update the Routes to use the guards
We need to add the guards to the routes array as shown below.
{path: 'foo/:name', component: SuccessComponent, canActivate : [UserAuthentication]} |
The above code adds the canActivate guard (UserAuthentication) to the foo path. When the user navigates to the /foo link the Angular calls the canActivate method from the UserAuthentication. If the method returns true then the SuccessComponent is rendered. We can add more than one guard as shown below:
{path: 'foo/:name', component: SuccessComponent, canActivate : [UserAuthentication, NameValidationService ]} |
The syntax for adding other guards are also similar
{ path: 'product', component: ProductComponent, canActivate : any[], canActivateChild: any[], canDeactivate: any[], canLoad: any[], resolve: any[] } |
Order of execution of route guards
A route can have multiple guards and you can have guards at every level of a routing hierarchy.
CanDeactivate() and CanActivateChild() guards are always checked first. The checking starts from the deepest child route to the top.
CanActivate() is checked next and checking starts from the top to the deepest child route.
CanLoad() is invoked next, If the feature module is to be loaded asynchronously
Resolve() is invoked last.
If any one of the guards returns false, then the entire navigation is canceled.
Angular Route Guards Example
app.component.ts
import { Component } from '@angular/core'; import { RouterLink, Router, RouterOutlet } from '@angular/router';
@Component( { selector: 'app-root', template: `
Enter Your Name : <input type="text" [(ngModel)]="name" /> <a [routerLink]="['/foo', name]">Submit</a>
<br/><br/> <router-outlet></router-outlet> `} ) export class AppComponent { name: string = "Manu"; constructor( private router: Router ) { } } |
userauthentication.service.ts
import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';
@Injectable() export class UserAuthentication implements CanActivate { name: string; constructor(private _router:Router ) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { this.name = route.params['name']; if (this.name == 'Manu') { return true; } else { this._router.navigate(["failure",this.name ]); return false; } } } |
success.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router';
@Component( { selector: 'app-first', template: ` Hello {{name}}, You are welocome! `} ) export class SuccessComponent { name: string; constructor( private _Activatedroute: ActivatedRoute, private _router: Router) {} ngOnInit() { this._Activatedroute.params.subscribe(params => { this.name = params['name']; }); } } |
failure.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; @Component( { selector: 'app-first', template: ` Hello {{name}}, You are not welocome! `} ) export class FailureComponent { name: string; constructor( private _Activatedroute: ActivatedRoute, private _router: Router) {} ngOnInit() { this._Activatedroute.params.subscribe(params => { this.name = params['name']; }); } } |
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { FormsModule } from '@angular/forms';
import { AppComponent } from './02Route_Guards/app.component'; import { SuccessComponent } from './02Route_Guards/success.component'; import { FailureComponent } from './02Route_Guards/failure.component'; import { UserAuthentication } from './02Route_Guards/userauthentication.service';
const routes: Routes = [ {path: 'foo/:name', component: SuccessComponent, canActivate : [UserAuthentication]}, {path: 'failure/:name', component: FailureComponent} ]; @NgModule({ declarations: [ AppComponent, SuccessComponent, FailureComponent ], imports: [ BrowserModule, FormsModule, RouterModule.forRoot(routes,{useHash : true}) ], providers: [UserAuthentication], bootstrap: [AppComponent] }) export class AppModule {} |
Output
All Chapters