×
☰ 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 CanActivateCanDeactivateResolveCanLoad, 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

  1. Build the Guard as Service. 

  2. Implement the Guard Method in the Service 

  3. Register the Guard Service in the Root Module 

  4. 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

angular-routing-security-route-guards-0
 
angular-routing-security-route-guards-1
 

All Chapters
Author