Angular CanActivate Guard Example

The Angular CanActivate guard runs before we navigate to a route allowing us to cancel the navigation. In this tutorial, we will learn what is CanActivate guard is and how to use it to protect the route. We will build a simple CanActivate Example app to show you how to use it in real application

What is CanActivate Guard

The Angular CanActivate guard decides, if a route can be activated ( or component gets rendered). We use this guard, when we want to check on some condition, before activating the component or showing it to the user. This allows us to cancel the navigation.

Use cases for the CanActivate Guard

  • Checking if a user has logged in
  • Checking if a user has permission

One of the use case of this guard is to check if the user has logged in to the system. If user has not logged in, then the guard can redirect him to login page.

How to use CanActivate Guard

First, we need to create a Angular Service.

The service must import & implement the CanActivate Interface. This Interface is defined in the @angular/router module. The Interface has one method i.e. canActivate. We need to implement it in our Service. The details of the CanActivate interface is as shown below.

interface CanActivate {
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
}

The method gets the instance of the ActivatedRouteSnapshot & RouterStateSnapshot. We can use this to get access to the route parameter, query parameter etc.

The guard must return true/false or a UrlTree . The return value can be in the form of observable or a promise or a simple boolean value.

A route can have more than one canActivate guard.

If all guards returns true, navigation to the route will continue.

If any one of the guard returns false, navigation will be cancelled.

If any one of the guard returns a UrlTree, current navigation will be cancelled and a new navigation will be kicked off to the UrlTree returned from the guard.

The example of canActivate guard is as follows

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


@Injectable()
export class AuthGuardService implements CanActivate {

    constructor(private _router:Router ) {
    }

    canActivate(route: ActivatedRouteSnapshot,
                state: RouterStateSnapshot): boolean {

        //check some condition  
        if (someCondition)  {
            alert('You are not allowed to view this page');
            //redirect to login/home page etc
            //return false to cancel the navigation
            return false;
        } 
        return true;
    }

}

Update the route definition with the canActivate guard as shown below. You can apply more than one guard to a route and a route can have more than one guard

{ path: 'product', component: ProductComponent, canActivate : [AuthGuardService] },

CanActivate guard Example

In our example application, we will create three components. The HomeComponent & ContactComponent are not protected and can be accessed any user. The user must log in into the system to access the ProductComponent..We also need a LoginComponent to handle the user login.

LoginComponent

The following is the code for LoginComponent and associated AuthService

[tabby title=”login.component.ts”]

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { AuthService } from './auth.service';

@Component({
   templateUrl: './login.component.html',
   styles: [``]
})
export class LoginComponent implements OnInit { 

    invalidCredentialMsg: string;
    username:string;
    password:string;
    retUrl:string="home";

    constructor(private authService: AuthService, 
                private router: Router, 
                private activatedRoute:ActivatedRoute) {
    }

    ngOnInit() {
        this.activatedRoute.queryParamMap
                .subscribe(params => {
            this.retUrl = params.get('retUrl'); 
            console.log( 'LoginComponent/ngOnInit '+ this.retUrl);
        });
    }

    onFormSubmit(loginForm) {
       this.authService.login(loginForm.value.username, loginForm.value.password).subscribe(data => {
           console.log( 'return to '+ this.retUrl);
           if (this.retUrl!=null) {
                this.router.navigate( [this.retUrl]);
           } else {
                this.router.navigate( ['home']);
           }
       });
    }
} 

[tabby title=”login.component.html”]

<h3>Login Form</h3>

<div>
	<form #loginForm="ngForm" (ngSubmit)="onFormSubmit(loginForm)">
	  <p>User Name: <input type='text'  name='username' ngModel></p>
	  <p>Password: <input type="password"  name="password" ngModel></p>
	  <p><button type="submit">Submit</button></p> 
	</form>
</div> 

[tabby title=”auth.service.ts”]

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import { of } from 'rxjs';

@Injectable()
export class AuthService { 

    private isloggedIn: boolean;
    private userName:string;

    constructor() {
        this.isloggedIn=false;
    }

    login(username: string, password:string) {

        //Assuming users are provided the correct credentials.
        //In real app you will query the database to verify.
        this.isloggedIn=true;
        this.userName=username;
        return of(this.isloggedIn);
    }

    isUserLoggedIn(): boolean {
        return this.isloggedIn;
    }

    isAdminUser():boolean {
        if (this.userName=='Admin') {
            return true; 
        }
        return false;
    }
    
    logoutUser(): void{
        this.isloggedIn = false;
    }

} 

[tabbyending]

The AuthService checks whether the user is allowed to login. It has the method to login & logout the users. Our implementation of the login method does not check for anything. It just marks the user as logged in.

ProductComponent

The ProductComponent is our protected component. Only the logged in users can access this. This component displays the list of Products, which it gets from the ProductService.

[tabby title=”product.component.ts”]

import { Component, OnInit } from '@angular/core';
import { ProductService } from './product.service';
import { Product } from './Product';


@Component({
  templateUrl: "product.component.html",
})
export class ProductComponent
{

   products:Product[];
   constructor(private productService: ProductService){
   }

   ngOnInit() {

      this.productService.getProducts()
        .subscribe(data => {
          this.products=data;
        })
   }
  
}

[tabby title=”product.component.html”]

<h1>Product List</h1>
   <p> This is a protected component </p>

   <div class='table-responsive'>
   <table class='table'>
       <thead>
           <tr>
               <th>Name</th>
               <th>Price</th>
           </tr>
       </thead>
       <tbody>
           <tr *ngFor="let product of products;">
               <td><a>{{product.name}} </a> </td>
               <td>{{product.price}}</td>
           </tr>
       </tbody>
     </table>
  </div>

[tabby title=”product.service.ts”]

import {Product} from './Product'
import { of, Observable, throwError} from 'rxjs';
import { delay, map } from 'rxjs/internal/operators';

export class ProductService{

    products: Product[];
    
    public constructor() {
        this.products=[
            new Product(1,'Memory Card',500),
            new Product(2,'Pen Drive',750),
            new Product(3,'Power Bank',100),
            new Product(4,'Computer',100),
            new Product(5,'Laptop',100),
            new Product(6,'Printer',100),
        ]
    }

    public getProducts(): Observable<Product[]> {
        return of(this.products) ;
    }

    public getProduct(id): Observable<Product> {
        var Product= this.products.find(i => i.productID==id)
        return of(Product) ;
    }

}

[tabby title=”product.ts”]

export class Product { 

    constructor(productID:number,    name: string ,   price:number) {
        this.productID=productID;
        this.name=name;
        this.price=price;
    }

    productID:number ;
    name: string ;
    price:number;

}

[tabbyending]

Other Component

[tabby title=”app.component.ts”]

import { Component } from '@angular/core';
import { AuthService } from './auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  title = 'Routing Module - Route Guards Demo';

  constructor (private authService:AuthService, 
               private router:Router) {
  }

  logout() {
    this.authService.logoutUser();
    this.router.navigate(['home']);
  }

}

[tabby title=”app.component.html”]

<div class="container">

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <div class="navbar-header">
      <a class="navbar-brand" [routerLink]="['/']"><strong> {{title}} </strong></a>
    </div>
    <ul class="nav navbar-nav">

        <li><a [routerLink]="['home']">Home</a></li>
        <li><a [routerLink]="['product']">Product</a></li>
        <li><a [routerLink]="['contact']">Contact us</a></li>
        <li><a [routerLink]="['login']">Login</a></li>
        <li><a [routerLink]="" (click)="logout()">Log out</a></li>
        
    </ul>
  </div>
</nav>

 <router-outlet></router-outlet>

</div>

[tabby title=”home.component.ts”]

import {Component} from '@angular/core';

@Component({
    template: `<h1>Welcome!</h1>
              <p>This is Home Component </p>
             `
})

export class HomeComponent {
}

[tabby title=”contact.component.ts”]

import {Component} from '@angular/core';

@Component({
     template: `<h1>Contact Us</h1>
                <p>TekTutorialsHub </p>
                `
})
export class ContactComponent {
}

[tabbyending]

CanActivate Guard

Finally, we build a CanActivate guard, which will check whether the users are logged in or not. If users are not logged in, then they are redirected to the login page.

[tabby title=”auth-guard.service.ts”]

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot,RouterStateSnapshot, UrlTree } from '@angular/router';
import { AuthService } from './auth.service';


@Injectable()
export class AuthGuardService implements CanActivate {

    constructor(private router:Router, private authService: AuthService ) {

    }

    canActivate(route: ActivatedRouteSnapshot,
                state: RouterStateSnapshot): boolean|UrlTree {

        if (!this.authService.isUserLoggedIn()) {
            alert('You are not allowed to view this page. You are redirected to login Page');
            
            this.router.navigate(["login"],{ queryParams: { retUrl: route.url} });
            return false;

            //var urlTree = this.router.createUrlTree(['login']);
            //return urlTree;
        } 

        return true;
    }

}

[tabbyending]

First, we import the CanActivate from the @angular/router module.

The AuthGuardService implements the CanActivate interface

Inject the AuthServce in the constructor of the Guard

In the CanActivate method, we will redirect the user the login page, if the user is not logged in. To cancel the navigation ,we must either return false or urlTree as shown in the example above.

Next, we will update the route definition and use the guard in all the routes, which we want to protect

[tabby title=”app.routes.ts”]

import { Routes } from '@angular/router';

import { HomeComponent} from './home.component'
import { ContactComponent} from './contact.component'
import { ProductComponent} from './product.component'

import { AuthGuardService } from './auth-guard.service';
import { LoginComponent } from './login.component';


export const appRoutes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'login', component:LoginComponent},
  { path: 'contact', component: ContactComponent },
  { path: 'product', component: ProductComponent, canActivate : [AuthGuardService] },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
];

[tabbyending]

Finally, register the service in the app.module.

[tabby title=”app.module.ts”]

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule }    from '@angular/forms';

import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { HomeComponent} from './home.component'
import { ContactComponent} from './contact.component'
import { ProductComponent} from './product.component'

import { AuthGuardService } from './auth-guard.service';

import { appRoutes } from './app.routes';
import { AuthService } from './auth.service';
import { LoginComponent } from './login.component';
import { ProductService } from './product.service';

@NgModule({
  declarations: [
    AppComponent,HomeComponent,ContactComponent,ProductComponent,LoginComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [AuthGuardService,AuthService, ProductService],
  bootstrap: [AppComponent]
})
export class AppModule { }

[tabbyending]

Run the app. You can access the Product page only if you login as shown in the image below.

Angular CanActivate guard Example

Reference

CanActivate Interface

14 thoughts on “Angular CanActivate Guard Example”

  1. Hi,
    I am facing issue like cannot access inside canActivate() method I am not able to see console values. initialized authguardservice in providers while debug found that its not calling inside canActivate method can you please help in this issue.

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    console.log(“check”)
    return true;
    }

  2. Hi,
    I am facing this issue like in authguardservice file inside canActivate method console is not printing. I have added authguardservice in providers…
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    console.log(“check”)
    return true;
    }

  3. Hi,
    How do I apply this algorithm to hide or show component without navigate anywhere. In the other words, I have index page and 2 components. User will be validated in “A” component. If validation is pass, He will be seeing “B” component… should I just modify this line: { path: ‘product’, component: ProductComponent, canActivate : [AuthGuardService] },

    Thank you

  4. Hello if I want to give access module wise then how to do so?

    I mean to say if you have component A ,component B and component C

    And I have user harry which has access rights of A and B.

    Then I have jack who has access rights of B and C

    How can we achieve that?

    1. Setup a role for each component. You can use route data to store role [ Refer Pass data to route]

      Load the user role when user logs in.

      Match the user role with the component role and in the CanActivate Guard.

      Google “Role Based Authorization in Angular”, you will get several articles

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top