Policy-Based Authorization In Angular Using JWT
Tags: angular, aspnetcore, security, csharp
Published: 2019-12-12 17:23:43

---
title: Policy-Based Authorization In Angular Using JWT
published: true
date: 2019-11-25 05:31:00 UTC
tags: Angular,ASP.NET Core,security,csharp
canonical_url: https://ankitsharmablogs.com/policy-based-authorization-in-angular-using-jwt/
---

## Introduction

In this article, we will create a web application using ASP.NET Core and Angular. We will then implement authentication and policy-based authorization in the application with the help of JWT. The web application will have two roles – Admin and User. The application will have role-based access for each role. We will learn how to configure and validate a JWT.

Take a look at the final application.

![Policy-Based Authorization In Angular Using JWT_Demo](https://i0.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/ngjwt.gif?w=648&ssl=1)

## Prerequisites

- Install the latest .NET Core 3.0 SDK from [here](https://dotnet.microsoft.com/download)
- Install the latest version of Visual Studio 2019 from [here](https://visualstudio.microsoft.com/downloads/)

## Source Code

Get the source code from [GitHub](https://github.com/AnkitSharma-007/jwt-authentication-authorization-angular-aspnetcore)

## What is JWT?

JWT stands for JSON Web Token. It is an open standard that defines a compact and self-contained way to securely transfer the data between two parties. JWT is digitally signed hence it can be verified and trusted. JWT is recommended to be used in a scenario when we need to implement Authorization or information exchange. To explore JWT in-depth please refer to the [official website of JWT](https://jwt.io/).

## Creating the ASP.NET Core application

Open Visual Studio 2019 and click on “Create a new Project”. A “Create a new Project” dialog will open. Select “ASP.NET Core Web Application” and click on Next. Refer to the image shown below.

![Policy-Based Authorization In Angular Using JWT](https://i1.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/CreateProj_1.png?w=648&ssl=1)

Now you will be at “Configure your new project” screen, provide the name for your application as ngWithJWT and click on create. You will be navigated to “Create a new ASP.NET Core web application” screen. Select “.NET Core” and “ASP.NET Core 3.0” from the dropdowns on the top. Then, select “Angular” project template and click on Create. Refer to the image shown below.

![Policy-Based Authorization In Angular Using JWT](https://i0.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/CreateProj_2.png?w=648&ssl=1)

This will create our project. The folder structure of our application is shown below.

![Policy-Based Authorization In Angular Using JWT](https://i1.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/Sol_Exp.png?w=648&ssl=1)

The `ClientApp` folder contains the Angular code for our application. The Controllers folders will contain our API controllers. The angular components are present inside the `ClientApp\src\app` folder. The default template contains few Angular components. These components won’t affect our application, but for the sake of simplicity, we will delete fetchdata and counter folders from `ClientApp/app/components` folder. Also, remove the reference for these two components from the `app.module.ts` file.

## Adding the Model to the Application

Right-click on the project and select Add \>\> New Folder. Name the folder as Models. Now right-click on the Models folder and select Add \>\> class. Name the class file as `User.cs`. This file will contain the User model. Put the following code in this class.

```csharp
using System;

namespace ngWithJwt.Models
{
    public class User
    {
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string Password { get; set; }
        public string UserType { get; set; }
    }
}
```

Similarly, add a new class and name it `Policies.cs`. This class will define the policies for role-based authorization. Put the following code into it.

```csharp
using Microsoft.AspNetCore.Authorization;
using System;
namespace ngWithJwt.Models
{
    public static class Policies
    {
        public const string Admin = "Admin";
        public const string User = "User";
        public static AuthorizationPolicy AdminPolicy()
        {
            return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().RequireRole(Admin).Build();
        }
        public static AuthorizationPolicy UserPolicy()
        {
            return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().RequireRole(User).Build();
        }
    }
}
```

We have also created two policies for authorization. The `AdminPolicy` method will check for the “Admin” role while validating a request. Similarly, the `UserPolicy` method will check for the “User” role while validating the request. We will register both of these policies in the `ConfigureServices` method of Startup.cs file later in this article.

## Configure appsettings.json

Add the following lines in `appsettings,json` file.

```json
"Jwt": {
  "SecretKey": "KqcL7s998JrfFHRP",
  "Issuer": "https://localhost:5001/",
  "Audience": "https://localhost:5001/"
}
```

Here we have defined a JSON config for the secret key to be used for encryption. We have also defined the issuer and audience for our JWT. You can use the localhost URL as the value for these properties.

> We will be using HmacSha256 as our encryption algorithm for JWT. This algorithm requires a key size of 128 bits or 16 bytes. Hence make sure that your key must satisfy this criterion, otherwise, you will get a run time error .

## Install NuGet package 

We will install the `AspNetCore.Authentication.JwtBearer` NuGet package to configure ASP.NET Core middleware for JWT authentication and authorization. Navigate to [NuGet gallery](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer/) page for this package. Select the version of .NET Core 3 from the “Version History”. Copy the command from the “package manager” tab. Run this command in the NuGet package manager console of our application. For this application, we are using .NET Core 3.0.0. Therefore, we will run the following command in the package manager console of our application.

```
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 3.0.0
```

Refer to the image below.

![Policy-Based Authorization In Angular](https://i1.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/nuget.png?w=648&ssl=1)

## Adding the Login Controller

We will add a Login Controller to our application which will handle the Login request from the user. Right-click on the Controllers folder and select Add \>\> New Item. An “Add New Item” dialog box will open. Select Web from the left panel, then select “API Controller Class” from templates panel and put the name as `LoginController.cs`. Click on Add. Refer to the image below.

![Policy-Based Authorization In Angular Using JWT](https://i1.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/LoignController.png?w=648&ssl=1)

Open `LoginController.cs` file and put the following code into it.

```csharp
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using ngWithJwt.Models;

namespace ngWithJwt.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class LoginController : Controller
    {
        private readonly IConfiguration _config;

        private List<User> appUsers = new List<User>
        {
            new User {  FirstName = "Admin",  UserName = "admin", Password = "1234", UserType = "Admin" },
            new User {  FirstName = "Ankit",  UserName = "ankit", Password = "1234", UserType = "User" }
        };

        public LoginController(IConfiguration config)
        {
            _config = config;
        }

        [HttpPost]
        [AllowAnonymous]
        public IActionResult Login([FromBody]User login)
        {
            IActionResult response = Unauthorized();
            User user = AuthenticateUser(login);
            if (user != null)
            {
                var tokenString = GenerateJWT(user);
                response = Ok(new
                {
                    token = tokenString,
                    userDetails = user,
                });
            }
            return response;
        }

        User AuthenticateUser(User loginCredentials)
        {
            User user = appUsers.SingleOrDefault(x => x.UserName == loginCredentials.UserName && x.Password == loginCredentials.Password);
            return user;
        }

        string GenerateJWT(User userInfo)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, userInfo.UserName),
                new Claim("firstName", userInfo.FirstName.ToString()),
                new Claim("role",userInfo.UserType),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            };

            var token = new JwtSecurityToken(
                issuer: _config["Jwt:Issuer"],
                audience: _config["Jwt:Audience"],
                claims: claims,
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: credentials
            );
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}
```

Here we have created a list of users called `appUsers`. We will use this list to verify user credentials. We are using a hard-coded list for simplicity. Ideally, we should store the user credentials in the database and make a DB call to verify the details. The `Login` method will receive the login details of the user and then verify it by calling the `AuthenticateUser` method. The `AuthenticateUser` method will check if the user details exist in the user list `appUsers`. If the user details exist, then the method will return an object of type User else it will return null. If the user details are verified successfully, we will invoke the `GenerateJWT` method.

The `GenerateJWT` method will configure the JWT for our application. We are using `HmacSha256` as our encryption algorithm. We will also create claims to be sent as payload with our JWT. The claims will contain info about the user such as UserName, FirstName, and UserType. We will use this information on the client app. In the end, we will create the JWT by specifying details such as issuer, audience, claims, expire and signingCredentials. We are setting the expiry time as 30 mins from the time of the creation of token. We will send the JWT token back to the client with an OK response. If the user details are invalid, we will send an Unauthorized response.

## Configuring Startup.cs file

We will configure the request pipeline for the application in the `startup.cs` file. This will handle the incoming requests for our application. We will add the following code snippet in `ConfigureServices` method. You can also check the full method definition on [GitHub](https://github.com/AnkitSharma-007/jwt-authentication-authorization-angular-aspnetcore/blob/master/ngWithJwt/Startup.cs#L25-L59).

```csharp
public void ConfigureServices(IServiceCollection services)
{
	services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
	.AddJwtBearer(options =>
	{
		options.RequireHttpsMetadata = false;
		options.SaveToken = true;
		options.TokenValidationParameters = new TokenValidationParameters
		{
			ValidateIssuer = true,
			ValidateAudience = true,
			ValidateLifetime = true,
			ValidateIssuerSigningKey = true,
			ValidIssuer = Configuration["Jwt:Issuer"],
			ValidAudience = Configuration["Jwt:Audience"],
			IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])),
			ClockSkew = TimeSpan.Zero
		};
		services.AddCors();
	});

	services.AddAuthorization(config =>
	{
		config.AddPolicy(Policies.Admin, Policies.AdminPolicy());
		config.AddPolicy(Policies.User, Policies.UserPolicy());
	});

...
  Existing code in the method.
..
}
```

We are adding the JWT authentication scheme using the `AddAuthentication` method. We have provided the parameters to validate the JWT. The description for each parameter is as shown below:

- ValidateIssuer = true: It will verify if the issuer data available in JWT is valid.
- ValidateAudience = true:  It will verify if the audience data available in JWT is valid.
- ValidateLifetime = true: It will verify if the token has expired or not
- ValidateIssuerSigningKey = true: It will verify if the signing key is valid and trusted by the server.
- ValidIssuer: A string value that represents a valid issuer that will be used to check against the token’s issuer We will use the same value as we used while generating JWT.
- ValidAudience: A string value that represents a valid audience that will be used to check against the token’s audience. We will use the same value which we used while generating JWT.
- IssuerSigningKey: The secure key used to sign the JWT.
- ClockSkew: It will set the clock skew to apply when validating the expiry time.

> The default value for ClockSkew is 300 seconds i.e. 5 mins. This means that a default value of 5 mins will be added to the expiry time of JWT. E.g. in our case we have set the expiry time as 30 mins but actually it will be 30 + 5 = 35 mins. Hence, we have set the ClockSkew to zero so that the expiry time of JWT will remain the same as we set while generating it.

We will register our authorization policies in the `ConfigureServices` method. The extension method `AddAuthorization` is used to add authorization policy services. To apply these policies, we will use the `Authorize` attribute on any controller or endpoint we want to secure.

To enable authentication and authorization in our application, we will add the `UseAuthentication` and `UseAuthorization` extension methods in the Configure method of `Startup` class. The code snippet is shown below. You can also check the full method definition on [GitHub](https://github.com/AnkitSharma-007/jwt-authentication-authorization-angular-aspnetcore/blob/master/ngWithJwt/Startup.cs#L62-L106).

```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	...
	// Existing code
	...

	if (!env.IsDevelopment())
	{
		app.UseSpaStaticFiles();
	}
	app.UseRouting();

	app.UseAuthentication();
	app.UseAuthorization();

	app.UseEndpoints(endpoints =>
	{
		endpoints.MapControllerRoute(
			name: "default",
			pattern: "{controller}/{action=Index}/{id?}");
	});
	
	...
	// Existing code
	...
}
```

## Adding the User Controller

We will add a user controller to handle all user-specific requests. Add a new API controller class, `UserController.cs` and put the following code into it.

```csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ngWithJwt.Models;

namespace ngWithJwt.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class UserController : Controller
    {
        [HttpGet]
        [Route("GetUserData")]
        [Authorize(Policy = Policies.User)]
        public IActionResult GetUserData()
        {
            return Ok("This is an normal user");
        }

        [HttpGet]
        [Route("GetAdminData")]
        [Authorize(Policy = Policies.Admin)]
        public IActionResult GetAdminData()
        {
            return Ok("This is an Admin user");
        }
    }
}
```

We have defined two methods, one for each role. Both the method will return a simple string to the client. We are using the `Authorize` attribute with the policy name to implement policy-based authorization to our controller methods.

## Working on the Client side of the application

The code for the client-side is available in the ClientApp folder. We will use Angular CLI to work with the client code.

> Using Angular CLI is not mandatory. I am using Angular CLI here as it is user-friendly and easy to use. If you don’t want to use CLI then you can create the files for components and services manually.

## Install Angular CLI

You can skip this step if Angular CLI is already installed in your machine. Open a command window and execute the following command to install angular CLI in your machine.

```
npm install -g @angular/CLI
```

After the Angular CLI is installed successfully, navigate to `ngWithJWT\ClientApp` folder and open a command window. We will execute all our Angular CLI commands in this window.

## Create the models

Create a folder called models inside the `ClientApp\src\app` folder. Now we will create a file `user.ts` in the models folder. Put the following code in it.

```typescript
export class User {
    userName: string;
    firstName: string;
    isLoggedIn: boolean;
    role: string;
}
```

Similarly, create another file inside the models folder called `roles.ts`. This file will contain an enum, which will define roles for our application. Put the following code in it.

```
export enum UserRole {
    Admin = 'Admin',
    User = 'User'
}
```

## Create the User Service

We will create an Angular service which will convert the Web API response to JSON and pass it to our component. Run the following command.

```
ng g s services\user
```

This command will create a folder with name services and then create the following two files inside it.

1. user.service.ts – the service class file.
2. user.service.spec.ts – the unit test file for service.

Open user.service.ts file and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class UserService {

  myAppUrl = '';

  constructor(private http: HttpClient) {
  }

  getUserData() {
    return this.http.get('/api/user/GetUserData').pipe(map(result => result));
  }

  getAdminData() {
    return this.http.get('/api/user/GetAdminData').pipe(map(result => result));
  }
}
```

We have defined two methods here to invoke our API endpoints. The method `getUserData` will invoke the `GetUserData` method from the User Controller to fetch the user data. The `getAdminData` method will invoke the `GetAdminData` method from the User Controller to fetch the Admin data.

## Create the Auth Service

Run the following command to create the auth service class.

```
ng g s services\auth
```

Open `auth.service.ts` and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { Router } from '@angular/router';
import { User } from '../models/user';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  userData = new BehaviorSubject<User>(new User());

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

  login(userDetails) {
    return this.http.post<any>('/api/login', userDetails)
      .pipe(map(response => {
        localStorage.setItem('authToken', response.token);
        this.setUserDetails();
        return response;
      }));
  }

  setUserDetails() {
    if (localStorage.getItem('authToken')) {
      const userDetails = new User();
      const decodeUserDetails = JSON.parse(window.atob(localStorage.getItem('authToken').split('.')[1]));

      userDetails.userName = decodeUserDetails.sub;
      userDetails.firstName = decodeUserDetails.firstName;
      userDetails.isLoggedIn = true;
      userDetails.role = decodeUserDetails.role;

      this.userData.next(userDetails);
    }
  }

  logout() {
    localStorage.removeItem('authToken');
    this.router.navigate(['/login']);
    this.userData.next(new User());
  }
}
```

The login method will invoke the Login API method to validate the user details. If we get an OK response from the API, we will store the JWT in the local storage. The `setUserDetails` method will extract the payload data from JWT and store it in a `BehaviorSubject` object called `userData`. The logout method will clear the local storage and navigate the user back to the login page. It will also reset the `userData` object.

## The Login Component

Run the following command in the command prompt to create the Login component.

```
ng g c login --module app
```

The `--module` flag will ensure that this component will get registered at app.module.ts. Open `login.component.ts` and put the following code in it.

```typescript
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { first } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';

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

  loading = false;
  loginForm: FormGroup;
  submitted = false;
  returnUrl: string;

  constructor(private formBuilder: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
    private authService: AuthService) { }

  ngOnInit() {
    this.loginForm = this.formBuilder.group({
      username: ['', Validators.required],
      password: ['', Validators.required]
    });
  }

  get loginFormControl() { return this.loginForm.controls; }

  onSubmit() {
    this.submitted = true;
    if (this.loginForm.invalid) {
      return;
    }
    this.loading = true;
    const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
    this.authService.login(this.loginForm.value)
      .pipe(first())
      .subscribe(
        () => {
          this.router.navigate([returnUrl]);
        },
        () => {
          this.loading = false;
          this.loginForm.reset();
          this.loginForm.setErrors({
            invalidLogin: true
          });
        });
  }
}
```

Open `login.component.html` and put the following code in it.

```html
<div class="col-md-6 offset-md-3 mt-5">
  <div *ngIf="loginForm.errors?.invalidLogin" class="alert alert-danger mt-3 mb-0">
    Username or Password is incorrect.
  </div>
  <div class="card">
    <h5 class="card-header">JWT authentication with Angular and .NET Core 3</h5>
    <div class="card-body">
      <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
        <div class="form-group">
          <label for="username">Username</label>
          <input type="text" formControlName="username" class="form-control" tabindex="1" autofocus
            [ngClass]="{ 'is-invalid': submitted && loginFormControl.username.errors }" />
          <div *ngIf="submitted && loginFormControl.username.errors" class="invalid-feedback">
            <div *ngIf="loginFormControl.username.errors.required">Username is required</div>
          </div>
        </div>
        <div class="form-group">
          <label for="password">Password</label>
          <input type="password" formControlName="password" class="form-control" tabindex="2"
            [ngClass]="{ 'is-invalid': submitted && loginFormControl.password.errors }" />
          <div *ngIf="submitted && loginFormControl.password.errors" class="invalid-feedback">
            <div *ngIf="loginFormControl.password.errors.required">Password is required</div>
          </div>
        </div>
        <button [disabled]="loading" class="btn btn-primary">
          <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
          Login
        </button>
      </form>
    </div>
  </div>
</div>
```

We are creating a login form having two fields – Username and Password. Both the fields of the form are required fields. The `onSubmit` method will be called when we click on the Login button. We are using `formControlName` attribute to bind the input field to the loginForm controls. If the loginForm has invalidLogin error we will display an error message on the screen. We are using Bootstrap for styling the form.

## The User-home Component

The `UserHomeComponent` is accessible to the login with roles defined as “user”. Run the command mentioned below to create this component.

```
ng g c user-home --module app
```

Open the `user-home.component.ts` file and update the `UserHomeComponent` class by adding the code as shown below.

```typescript
export class UserHomeComponent implements OnInit {

  userData: string;

  constructor(private userService: UserService) { }

  ngOnInit() {
  }

  fetchUserData() {
    this.userService.getUserData().subscribe(
      (result: string) => {
        this.userData = result;
      }
    );
  }
}
```

We have defined a method `fetchUserData` which will invoke the `getUserData` method of the `UserService` class. This will return a string and we will store the result in a variable userData of type string.

Open the `user-home.component.html` file and put the following code inside it.

```html
<h2>This is User home page</h2>
<hr />
<button class="btn btn-primary" (click)=fetchUserData()>Fetch Data</button>
<br />
<br />
<div>
    <h4>
        {{userData}}
    </h4>
</div>
```

We have defined a button and invoking the `fetchUserData` on the button click. We are displaying the string value fetched from the API inside a `<h4>` tag.

## The Admin-home Component

The `AdminHomeComponent` is accessible to the login with roles defined as “admin”. Run the command mentioned below to create this component.

```
ng g c admin-home --module app
```

Open the `admin-home.component.ts` file and update the `AdminHomeComponent` class by adding the code as shown below.

```typescript
export class AdminHomeComponent implements OnInit {

  adminData: string;

  constructor(private userService: UserService) { }

  ngOnInit() {
  }

  fetchAdminData() {
    this.userService.getAdminData().subscribe(
      (result: string) => {
        this.adminData = result;
      }
    );
  }
}
```

We have defined a method `fetchAdminData` which will invoke the `getAdminData` method of the `UserService` class. This will return a string and we will store the result in a variable adminData of type string.

Open the `admin-home.component.html` file and put the following code inside it.

```html
<h2>This is Admin home page</h2>
<hr />
<button class="btn btn-primary" (click)=fetchAdminData()>Fetch Data</button>
<br />
<br />
<div>
    <h4>
        {{adminData}}
    </h4>
</div>
```

We have defined a button and invoking the `fetchAdminData` on the button click. We are displaying the string value fetched from the API inside a `<h4>` tag.

## Adding the links in Nav Menu

Open `nav-menu.component.ts` and update the `NavMenuComponent` class as shown below.

```typescript
export class NavMenuComponent {
  isExpanded = false;
  userDataSubscription: any;
  userData = new User();
  userRole = UserRole;

  constructor(private authService: AuthService) {
    this.userDataSubscription = this.authService.userData.asObservable().subscribe(data => {
      this.userData = data;
    });
  }

  collapse() {
    this.isExpanded = false;
  }

  toggle() {
    this.isExpanded = !this.isExpanded;
  }

  logout() {
    this.authService.logout();
  }
}
```

We are subscribing to the `userData` subject of the `AuthService` class in the constructor and setting the value of a local variable `userData`. We will use the properties of `userData` object to toggle the nav-menu links in the template file. The logout method will call the logout method of the `AuthService` class.

We will add the links for our components in the nav menu. Open `nav-menu.component.html` and remove the links for Counter and Fetch data components and add the following lines.

```html
<li class="nav-item" [routerLinkActive]='["link-active"]'>
	<a class="nav-link text-dark" *ngIf="!userData.isLoggedIn" [routerLink]='["/login"]'>Login</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]'>
	<a class="nav-link text-dark" *ngIf="userData.isLoggedIn && userData.role==userRole.User" [routerLink]='["/user-home"]' [routerLink]=''>UserHome</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]'>
	<a class="nav-link text-dark" *ngIf="userData.isLoggedIn && userData.role==userRole.Admin" [routerLink]='["/admin-home"]' [routerLink]=''>AdminHome</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]'>
	<a class="nav-link text-dark" *ngIf="userData.isLoggedIn" (click)=logout() [routerLink]=''>Logout</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]' *ngIf="userData.isLoggedIn">
	<a class="nav-link text-dark">Welcome <b>{{userData.firstName}}</b> </a>
</li>
```

Here we are displaying the links for `UserHome` and `AdminHome` based on the role of the user. We are also toggling between the Login and Logout button based on the `isLoggedIn` property of userData object. Clicking on the Login button will navigate the user to the login page whereas clicking on the logout button will invoke the logout method. We will also display the firstName of the user along with a welcome message once the user is authenticated.

## Securing the routes with route guards

To protect URL routes from unauthorized access we will create route guards. We will create two guards for protecting user routs and admin routes. Run the following commands to create an admin guard.

```
ng g g guards/admin --implements CanActivate
```

Here we are specifying the interfaces to implement using the implements flag. This command will create a folder name guards and add two files admin.guard.ts and admin.guard.spec.ts. Open admin.guard.ts file and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
import { User } from '../models/user';
import { UserRole } from '../models/roles';

@Injectable({
  providedIn: 'root'
})
export class AdminGuard implements CanActivate {
  userDataSubscription: any;
  userData = new User();
  constructor(private router: Router, private authService: AuthService) {
    this.userDataSubscription = this.authService.userData.asObservable().subscribe(data => {
      this.userData = data;
    });
  }

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    if (this.userData.role === UserRole.Admin) {
      return true;
    }

    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
    return false;
  }
}
```

We will subscribe to userData subject in the constructor of the AdminGuard class. We will override the canActivate method of the interface CanActivate. This method will return true if the user role is Admin otherwise it will set the returnUrl and navigate to the login page.

Similarly, we will create another guard to protect user routes. Run the command shown below.

```
ng g g guards/auth --implements CanActivate
```

Open auth.guard.ts file and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
import { User } from '../models/user';
import { UserRole } from '../models/roles';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  userDataSubscription: any;
  userData = new User();
  constructor(private router: Router, private authService: AuthService) {
    this.userDataSubscription = this.authService.userData.asObservable().subscribe(data => {
      this.userData = data;
    });
  }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    if (this.userData.role == UserRole.User) {
      return true;
    }

    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
    return false;
  }
}
```

This guard is similar to the AdminGuard. We will verify if the user role is User then return true else set the returnUrl and navigate to the login page.

## Add Http Interceptor

We will create an HTTP interceptor service to send the authorization token in the header of each API request. This will make sure that only the authorized user can access a particular API. Run the command shown below to create `HttpInterceptorService` class.

```
ng g s services\http-interceptor
```

Open the `http-interceptor.service.ts` file and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('authToken');
    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`,
        }
      });
    }
    return next.handle(request)
  }
}
```

The `HttpInterceptorService` class will implement the `HttpInterceptor` interface and override the intercept method. Inside this method, we will fetch the JWT from the localStorage. If the token exists we will modify the request header of the API call by assigning the token value to the Authorization property of headers.

## Add Error Interceptor 

We will add an error interceptor to intercept and handle the errors gracefully. This will make sure that the user experience is not hampered in case of any error from the server.

Run the command shown below to create `ErrorInterceptorService`.

```
ng g s services\error-interceptor
```

Open the `error-interceptor.service.ts` file and put the following code inside it.

```typescript
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ErrorInterceptorService implements HttpInterceptor {

  constructor(private authService: AuthService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(catchError(err => {
      if (err.status === 401) {
        this.authService.logout();
      }
      return throwError(err.status);
    }));
  }
}
```

This is similar to `HttpInterceptorService`. We will implement the `HttpInterceptor` interface and inside the intercept method, we will catch the error from `HttpRequest`. If we get error code as 401 i.e. unauthorized from the server, we will invoke the logout method for that user.

> In a real-world scenario, we should implement the refresh token feature upon getting an unauthorized error from the server. This will make sure that the user doesn’t get logged out frequently. Implementing refresh token on JWT is beyond the scope of this article but I will try to cover it in future article.

## Update App component

Open `app.component.ts` file and update the `AppComponent` class as shown below. This will make sure that the logged-in user data won’t be lost on page reload.

```typescript
export class AppComponent {
  constructor(private authService: AuthService) {
    if (localStorage.getItem('authToken')) {
      this.authService.setUserDetails();
    }
  }
}
```

## Update App module

At last, we will update the `app.module.ts` file by adding routes for our components and applying auth guards to the routes. We will also add our interceptors in the `providers` array. Update the `app.module.ts` file as shown below. You can refer to the [GitHub](https://github.com/AnkitSharma-007/jwt-authentication-authorization-angular-aspnetcore/blob/master/ngWithJwt/ClientApp/src/app/app.module.ts) for the complete code of this file.

```typescript
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
HttpClientModule,
FormsModule,
ReactiveFormsModule,
RouterModule.forRoot([
  { path: '', component: HomeComponent, pathMatch: 'full' },
  { path: 'login', component: LoginComponent },
  { path: 'user-home', component: UserHomeComponent, canActivate: [AuthGuard] },
  { path: 'admin-home', component: AdminHomeComponent, canActivate: [AdminGuard] }
])
],
providers: [{ provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptorService, multi: true },
],
bootstrap: [AppComponent]
```

## Execution Demo

Launch the application by pressing F5 from Visual Studio. You can perform the authentication and authorization as shown in the GIF below.

![Policy-Based Authorization In Angular Using JWT_Demo](https://i0.wp.com/ankitsharmablogs.com/wp-content/uploads/2019/11/ngjwt.gif?w=648&ssl=1)

## Summary

We have created an ASP.NET Core application and configured JWT authentication for it. We learned how JWT is configured and validated on the server. The application also has policy-based authorization. We defined two roles for our application and provided role-based access for each role. The client app is created using Angular. We also implemented interceptors for our client to send authorization token in the headers and to handle any error response coming from the server.

## See Also

- [Localization In Angular Using i18n Tools](https://ankitsharmablogs.com/localization-in-angular-using-i18n-tools/)
- [Understanding Angular Animation](https://ankitsharmablogs.com/understanding-angular-animation/)
- [ASP.NET Core – Expense Manager Using EF Core and Highcharts](https://ankitsharmablogs.com/asp-net-core-expense-manager-using-ef-core-and-highcharts/)
- [Facebook Authentication And Authorization In Server-Side Blazor App](https://ankitsharmablogs.com/facebook-authentication-and-authorization-in-server-side-blazor-app/)
- [Google Authentication And Authorization In Server-Side Blazor App](https://ankitsharmablogs.com/google-authentication-and-authorization-in-server-side-blazor-app/)
- [Blazor CRUD Using Google Cloud Firestore](https://ankitsharmablogs.com/blazor-crud-using-google-cloud-firestore/)

The post [Policy-Based Authorization In Angular Using JWT](https://ankitsharmablogs.com/policy-based-authorization-in-angular-using-jwt/) appeared first on [Ankit Sharma's Blog](https://ankitsharmablogs.com).