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.
At the time of writing the latest stable version for ASP.NET Core is 3.0 and that of Angular is 8.3
Take a look at the final application.

Prerequisites
- Install the .NET Core 3.0 SDK from https://dotnet.microsoft.com/download
- Install the latest version of Visual Studio 2019 from https://visualstudio.microsoft.com/downloads/
Source Code
Get the source code from GitHub
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.
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.

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.

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

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.
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.
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.
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 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.
Refer to the image below.

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.
Open
LoginController.cs file and put the following code into it.
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.
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.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.
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.
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.
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.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.
This command will create a folder with name services and then create the following two files inside it.
- user.service.ts – the service class file.
- user.service.spec.ts – the unit test file for service.
Open user.service.ts file and put the following code inside it.
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.
Open
auth.service.ts and put the following code inside it.
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.
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.
Open
login.component.html and put the following code in it.
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.
Open the
user-home.component.ts file and update the UserHomeComponent class by adding the code as shown below.
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.
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.
Open the
admin-home.component.ts file and update the AdminHomeComponent class by adding the code as shown below.
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.
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.
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.
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.
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.
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.
Open auth.guard.ts file and put the following code inside it.
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.
Open the
http-interceptor.service.ts file and put the following code inside it.
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.
Open the
error-interceptor.service.ts file and put the following code inside it.
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.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 for the complete code of this file.Execution Demo
Launch the application by pressing F5 from Visual Studio. You can perform the authentication and authorization as shown in the GIF below.

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.


0 comments:
Post a Comment
Note: only a member of this blog may post a comment.