Creating a Secure Role-Based App Using Angular Route Guard
Tags: angular, javascript, webdev, learning
Published: 2020-05-06 12:11:21

---
title: Creating a Secure Role-Based App Using Angular Route Guard
published: true
description: Setting up permissions based on user roles is a common use case in web apps. In this post, we explore how to set up secure routes with Angular route guard.
tags: angular, javascript, webdev, learning
canonical_url: https://blog.jscrambler.com/creating-a-secure-role-based-app-using-angular-route-guard/
cover_image: https://blog.jscrambler.com/content/images/2020/04/jscrambler-blog-create-secure-role-based-app-with-angular-route-guard.jpg
---

While creating a web app, setting up [permissions based on roles](https://blog.jscrambler.com/authentication-authorization-in-web-apps/#authorization?utm_source=dev.to&utm_medium=referral&utm_campaign=angular-route-guard) is a common scenario. Some users may have permissions to certain pages or certain sections of the pages depending on their user role.

In this tutorial, you'll learn how to create a role-based app using Angular route guard. The source code from this tutorial is available at [GitHub](https://github.com/JscramblerBlog/angularRoleApp).

## Setting Up the App
Let's start by setting up the Angular app. Assuming that you already have the Angular CLI installed, let's create a new Angular application.
```bash
ng new angular-role-app
```
The above command creates the basic boilerplate code for the Angular application. Navigate to the angular project folder and start the application.

```bash
cd angular-role-app
npm start
```
You will have the Angular app running at `localhost:4200`.

## Creating Angular Modules

Here are the three sections of our Angular application and their permissions:

- Administration section - accessible only by a superuser
- Management section - accessible only by a manager
- General section - accessible by any user

Let's create a module for each of the above sections. Create the Admin module by using the following Angular CLI command:

```bash
ng g module Administration --routing
```
Add two components to the `administration` module, `admin` and `adminHome`.

```bash
ng g component administration/admin
ng g component administration/adminHome
```

Let's also define the routing for the `administration` module as shown:

```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin/admin.component';
import { AdminHomeComponent } from './admin-home/admin-home.component';

const routes: Routes = [
  { path: '', children :[
    { path : 'adminHome', component : AdminHomeComponent },
    { path : 'admin', component : AdminComponent },
    { path : '', redirectTo : 'admin', pathMatch : 'full' }
  ] }
];

@NgModule({
  declarations: [],
  imports: [RouterModule.forChild(routes)],
  exports : [RouterModule]
})
export class AdminRoutingModule { }
```
Similarly, create the management and general section module using the command below. (The `--routing` option creates the routing file for each of the consecutive modules.)

```bash
ng g module general --routing
ng g module management --routing
```
Create a `dashboard` component inside the `general` module. 

```bash
ng g component general/dashboard
```
Define the routing for the `general` module as shown:

```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';

const routes: Routes = [
  { path: '', component: DashboardComponent }
];

@NgModule({
  declarations: [],
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

export class GeneralRoutingModule { }
```
Create a component called “management” inside the management module. 

```bash
ng g component management/management
```
Define the routing file for the management module as below:

```js
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ManagementComponent } from './management/management.component';

const routes: Routes = [
  { path: '', component: ManagementComponent }
];

@NgModule({
  declarations: [],
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

export class ManagementRoutingModule { }
```

To enable the user to log in, let's also create a Login component.

```bash
ng g component login
```

Now you have the required modules and components ready, also define the routing module for the Angular application in the `app-routing.module.ts` file:

```js
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { 
    path: 'admin', 
    loadChildren: () => import('./administration/administration.module').then(m => m.AdministrationModule) 
  },
  { 
    path: 'general', 
    loadChildren: () => import('./general/general.module').then(m => m.GeneralModule) 
  },
  { 
    path: 'manage', 
    loadChildren: () => import('./management/management.module').then(m => m.ManagementModule) 
  },
  { path: '', redirectTo : 'login', pathMatch:'full' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```
As seen in the above routing module routes, `LoginComponent` is the default component.

Let's implement the logic for the Login component which we'll use for securing our Angular application routes.

<a href="https://blog.jscrambler.com/how-to-protect-angular-code-against-theft-and-reverse-engineering/?utm_source=dev.to&utm_medium=referral&utm_campaign=angular-route-guard"><img alt="Protect your Angular App with Jscrambler" src="https://media.jscrambler.com/blog/V1-Angular.jpg"></a>

## Implementing the Login Component
Let's start by implementing the Login component which will authenticate the user. For the sake of this tutorial, you'll be hard coding the authentication process inside the Login component. This login process is for demonstration purposes only and should not be used in production apps.

You'll be using Bootstrap for styling the HTML pages. Install it on the Angular app using the following command:

```bash
npm install bootstrap jquery
```
Once done with the dependency installation, add the following style and script to the `angular.json` file:

```json
"styles": [
	"src/styles.css",
	"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
	"node_modules/jquery/dist/jquery.min.js",
	"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
```
Also add the following HTML code to the `login.component.html` file:

```html
<form class="form-signin">
    <img class="mb-4" src="/docs/4.4/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
    <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
    <label for="inputUsername" class="sr-only">Username</label>
    <input type="text" id="inputUsername" name="username" [(ngModel)]="username" class="form-control" placeholder="Username" required autofocus>
    <label for="inputPassword" class="sr-only">Password</label>
    <input type="password" id="inputPassword" name="password" [(ngModel)]="password" class="form-control" placeholder="Password" required>
   
    <button class="btn btn-lg btn-primary btn-block" (click)="handleLoginClick()" type="button">Sign in</button>
  </form>
```

And add the following code to the `login.component.ts` file:

```js
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  username;
  password;

  constructor(private http : HttpClient, private router : Router) { }

  ngOnInit(): void {
    
  }

  handleLoginClick(){
    if(this.username && this.password){
      this.authenticateUser(this.username);
    } else {
      alert('enter username and password');
    }
   
  }

  authenticateUser(userName){
    if(userName == "admin"){
      this.router.navigate(['/admin']);
    } else if(userName == "manager"){ 
      this.router.navigate(['/manage']);
    } else if(userName == "general"){
      this.router.navigate(['/general'])
    }
  }

}
```

**Note:** Authenticating using username as shown above is not a secure way of authentication. This is for demo purposes only. For more information on secure authentication, check [this tutorial](https://blog.jscrambler.com/authentication-authorization-in-web-apps/?utm_source=dev.to&utm_medium=referral&utm_campaign=angular-route-guard).

As seen in the `authenticateUser` method `in login.component.ts`, if the user role is admin, manager, or general user, he'll be redirected to the specific module.

Save the above changes and run the application. Try signing in as admin and you'll be redirected to the admin module.

## Securing Routes Using Angular Route Guard
There is an issue with the above implementation. The routes are not secure. If you log in as a general user and try to access `localhost:4200/admin`, the route will display the admin module. So how can we secure the routes for unauthorized access? 

First, you need to store the user information somewhere to identify the user. Let's keep the logged in user information in session storage.

Inside the `authenticateUser` method in `login.component.ts`, add the following line of code to keep the user information in session storage:

```js
sessionStorage.setItem("user", userName);
```
Here is how the `authenticateUser` method looks:

```js
  authenticateUser(userName){
    sessionStorage.setItem("user", userName);
    if(userName == "admin"){
      this.router.navigate(['/admin']);
    } else if(userName == "manager"){ 
      this.router.navigate(['/manage']);
    } else if(userName == "general"){
      this.router.navigate(['/general'])
    }
  }
```
Now, create a service called `routeGuard` using the Angular CLI command :

```bash
ng g service routeGuard
```
In this Angular service, you'll implement the Angular `CanActivate` guard interface to secure the Angular route. 

Here is how the `route-guard.service.ts` file looks :

```js
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot } from '@angular/router';

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

  constructor() { }

  public canActivate(route: ActivatedRouteSnapshot){
    return true;
  }
}
```
Add the above `RouterGuardService` to the routes defined in the `app-routing.module.ts` file's `admin` route.

```js
{ 
    path: 'admin', 
    canActivate : [RouteGuardService],
    loadChildren: () => import('./administration/administration.module').then(m => m.AdministrationModule) 
}
```
Here is how the `app-routing.module.ts` file looks :
```js
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { RouteGuardService } from './route-guard.service';

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { 
    path: 'admin', 
    canActivate : [RouteGuardService],
    loadChildren: () => import('./administration/administration.module').then(m => m.AdministrationModule) 
  },
  { 
    path: 'general', 
    loadChildren: () => import('./general/general.module').then(m => m.GeneralModule) 
  },
  { 
    path: 'manage', 
    loadChildren: () => import('./management/management.module').then(m => m.ManagementModule) 
  },
  { path: '', redirectTo : 'login', pathMatch:'full' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```
The `canActivate` method in `RouteGuardService` returns `true` at the moment. Let's add the logic to only allow access to the admin route by admin users.

```js
  public canActivate(route: ActivatedRouteSnapshot){
    let user = sessionStorage.getItem('user');
    if(user == 'admin'){
      return true;
    }
    return false;
  }
```
You can get the user information from the session storage and return `true` if the user is admin, else `false`.

Save the above changes and restart the Angular app. Log in as a general user and try to access the `localhost:4200/admin/` route. You will be redirected to the Login page.

Similarly, using Angular guards you can secure any of the other routes.

## Wrapping It Up

In this tutorial, you learned how to secure an Angular app route using route guards. Here, we only explored the Angular guards concept from a PoC point of view.

While implementing Angular guards, you can use other interfaces that Angular provides. To get an in-depth understanding, we recommend reading the [Angular route guard's documentation](https://angular.io/guide/router).

And since we're talking about security, learn how you can obfuscate and protect the source code of your Angular apps by following <a href="https://blog.jscrambler.com/how-to-protect-angular-code-against-theft-and-reverse-engineering/?utm_source=dev.to&utm_medium=referral&utm_campaign=angular-route-guard" target="_blank">our guide</a>.