Implement JWT Authentication in Asp.net Core 5 Web API [Token Base Auth]

/ / 14 Comments

Asp.net Core JWT token Authentication: Here in this article we learn a complete step-by-step process to implement Authentication in Asp.net Core Web API using JSON Web Token ie JWT. We must ensure that our APIs are protected and secure when developing them.

That is, we need to authenticate a user so that only valid users can consume our APIS. Using JWT we can easily implement Token Based Authentication in Asp.net Core and safeguard our application. You can also check once the access token is expired, then how to implement JWT refresh token in Asp.net Core application

What is JSON Web Token?

The RFC 7519 JSON Web Token (JWT) is an open, industry-standard technique for securely conveying claims between two parties. This means that data sent between two parties using JWT is digitally signed and can be easily confirmed and trusted.

In short, using JWT we can implement Authentication and Authorization in any Web Application with any backend stack i.e Asp.net Core, Java, NodeJs, Python, PHP etc... 

Steps to Implement JWT Authentication in Asp.net Core

  • Understanding JWT Authentication Workflow.
  • Create Asp.net Core Web API project
  • Install NuGet Package (JwtBearer)
  • Asp.net Core JWT appsetting.json configuration
  • Asp.net Core Startup.cs - configure services add JwtBearer
  • Create Models User, Tokens class
  • Create IJWTManagerRepository to Authenticate users and generate JSON Web Token.
  • Create UserController - Authenticate action method.

# Understanding JWT Authentication Workflow.

Here in the below image, we illustrate the JWT Authentication flow diagram in Asp.net Core Web API.



# Create Asp.net Core Web API project

Here first we create the ASP.NET Core Web API project am using Asp.net Core 5 version if you want you can also select a lower version i.e Asp.net Core 3.1 version.

# Install NuGet Package (JwtBearer)

After Asp.net Core 5 Web API project is created successfully, now we installed some NuGet packages by using Visual Studio Nuget Package Manager UI i.e  from Visual Studio IDE go to Tools --> NuGet Package Manager --> Manage NuGet Packages for Solution

The 2 NuGet packages which we need to implement JWT authentication in the Asp.net Core application are Microsoft.AspNetCore.Authentication.JwtBearer and System.IdentityModel.Tokens.Jwt.

(Above is the image of Nuget Package Manager UI)

# Asp.net Core JWT appsetting.json configuration

After the NuGet packages are installed, next we modify our appsetting.json file and add secret key and other configuration values. These values we needed further while generating JSON Web Token.

Our appsetting.json file looks similar to as written below:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "JWT": {
    "Key": "This is my supper secret key for jwt",
    "Issuer": "https://codepedia.info",
    "Audience": "codepedia.info"
  }
}

Here we added JWT new root element and it has 3 values i.e Key, Issuer, Audience with corresponding values.

# ASP.NET CORE Startup.cs - Configure services add JwtBearer

In Asp.net Core application Startup.cs file is the entry point of the application. It allows us to load configuration, register dependencies services and set the ordering of the request pipeline.

Now in Configure method we add UseAuthentication() middleware before UseAuthorization() middleware. Also in ConfigureServices method we configure services using AddAuthentication with AddJwtBearer.

Our Startup.cs file code look like as written below:

public void ConfigureServices(IServiceCollection services)
{
	services.AddAuthentication(x =>
	{
		x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
		x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
	}).AddJwtBearer(o =>
	{
		var Key = Encoding.UTF8.GetBytes(Configuration["JWT:Key"]);
		o.SaveToken = true;
		o.TokenValidationParameters = new TokenValidationParameters
		{
			ValidateIssuer = false,
			ValidateAudience = false,
			ValidateLifetime = true,
			ValidateIssuerSigningKey = true,
			ValidIssuer = Configuration["JWT:Issuer"],
			ValidAudience = Configuration["JWT:Audience"],
			IssuerSigningKey = new SymmetricSecurityKey(Key)
		};
	});

	services.AddSingleton<IJWTManagerRepository, JWTManagerRepository>();

	services.AddControllers();
}

Here using Configuration["JWT:Key"] we get the secret key from our appsetting.json file.


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}

	app.UseHttpsRedirection();
	app.UseRouting();

	app.UseAuthentication(); // This need to be added	
	app.UseAuthorization();
	app.UseEndpoints(endpoints =>
	{
	    endpoints.MapControllers();
	});
}

Note: In the Startup.cs file we need to import 2 namespaces i.e Microsoft.IdentityModel.Tokens and Microsoft.AspNetCore.Authentication.JwtBearer.

# Create Models Users, Tokens

Now we add a new folder named Models and add two new classes .i.e Users, Token. Our both classes file codes look like as written below.

Users.cs file code:

public class Users
{
	public string Name { get; set; }
	public string Password { get; set; }
}

User class has two properties i.e Name, and Password. We use this class later in our usercontroller action method for authenticating.

Tokens.cs file code:

public class Tokens
{
	public string Token { get; set; }
	public string RefreshToken { get; set; }
}	

Tokens class has two string properties i.e Token, and RefreshToken.

Once the user is authenticated successfully, we generate a JWT token and return it to this Tokens class object.

# Create an IJWTManagerRepository interface to Authenticate users and generate JSON Web Token.

Now we create a new folder named Repository, under which create a new interface as IJWTManagerRepository.

In the interface IJWTManagerRepository we add a new method Authenticate(Users u), which returns a valid JWT Token
Our IJWTManagerRepository.cs file code look like as written below:

using JWTWebAuthentication.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace JWTWebAuthentication.Repository
{
   public interface IJWTManagerRepository
    {
        Tokens Authenticate(Users users); 
    }
   
}

Next we create a new class file named as JWTManagerRepository.cs and inherit the interface IJWTManagerRepository.

Here we add Dictionary as UsersRecords, which contains our user record. You can do this with a database, as our primary focus is to implement JWT so am using a dictionary with dummy records.

Our final code to look like at written below:

public class JWTManagerRepository : IJWTManagerRepository
{
	Dictionary<string, string> UsersRecords = new Dictionary<string, string>
	{
		{ "user1","password1"},
		{ "user2","password2"},
		{ "user3","password3"},
	};

	private readonly IConfiguration iconfiguration;
	public JWTManagerRepository(IConfiguration iconfiguration)
	{
		this.iconfiguration = iconfiguration;
	}
	public Tokens Authenticate(Users users)
	{
		if (!UsersRecords.Any(x => x.Key == users.Name && x.Value == users.Password)) {
			return null;
		}

		// Else we generate JSON Web Token
		var tokenHandler = new JwtSecurityTokenHandler();
		var tokenKey = Encoding.UTF8.GetBytes(iconfiguration["JWT:Key"]);
		var tokenDescriptor = new SecurityTokenDescriptor
		{
		  Subject = new ClaimsIdentity(new Claim[]
		  {
			 new Claim(ClaimTypes.Name, users.Name)                    
		  }),
		   Expires = DateTime.UtcNow.AddMinutes(10),
		   SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey),SecurityAlgorithms.HmacSha256Signature)
		};
		var token = tokenHandler.CreateToken(tokenDescriptor);
		return new Tokens { Token = tokenHandler.WriteToken(token) };

	}
}

Here first we check if the user is valid or not. If the user is not valid, then we return null, else we generate JSON Web Token and return the Tokens class object.  

When using a JWT token, authorizations are based on the claims contained in the JWT token.

To set JWT token expiration time in Asp.net Core , we use the Expires parameter of SecurityTokenDescriptor, and set its value as whatever we want. We can use .AddMinutes() to set JWT token expire in minutes, or .AddHours() to set JWT token expire in hours.

Here in the above code we set the JWT token expiration time as 10 mins, hence after 10 mins the token gets invalid.

Note: We need to register IJWTManagerRepository service in our Startup.cs ConfigureServices method.

#Create UserController - Authenticate action method 

In the Controllers folder, we add a new controller named as UsersController and in its constructor we inject IJWTManagerRepository interface (Constructor Dependency Injection Pattern)

The UsersController has two Action methods one for authenticating the user and in response returns JSON Web Token (JWT). And another to display the list of users only if the user is authenticated by using JWT. 

Our UsersController code look like as written below:

[Authorize]
[Route("api/[controller]")]
[ApiController]  
public class UsersController : ControllerBase
{
	private readonly IJWTManagerRepository _jWTManager;

	public UsersController(IJWTManagerRepository jWTManager)
	{
		this._jWTManager = jWTManager;
	}

	[HttpGet]
	public List<string> Get()
	{
		var users = new List<string>
		{
			"Satinder Singh",
			"Amit Sarna",
			"Davin Jon"
		};

		return users;
	}

	[AllowAnonymous]
	[HttpPost]
	[Route("authenticate")]
	public IActionResult Authenticate(Users usersdata)
	{
		var token = _jWTManager.Authenticate(usersdata);

		if (token == null)
		{
			return Unauthorized();
		}

		return Ok(token);
	}
}

Here, at controller level we decorated with [Authorize] attribute, to ensure that no action methods are invoked without authentication.

Similarly, at the Authenticate IAction method, we decorated it with [AllowAnonymous] attribute, which overrides the [Authorize] attribute. This allows all users to access the Authenticate IAction method, which returns JWT access token if the user is legitimate.

The [Authorize] attribute is responsible of validating the token against the rules defined in Startup.cs ConfigureServices method.

Lets consume these API from Postman.

First we call Get request, to check whether we able to display users records, without any authentication.

As in Fig 1 in response it returns 401 Unauthorized

Fig1: 

Next now we call authenticate API with valid user credentials. As in Fig 2 in response we got JWT Token, which we used in header for authentication.

Fig2:


Now we again call the Get method, but with valid token, which we generated in previous call. As in Fig 3 we able to display user data, after proper authentication using JSON Web Token.

Fig 3:


Conclusion: Using JWT we successfully implement Token Base Authentication in ASP.NET CORE Web API. And with this, we were able to secure our WebAPI in Asp.net Core using JWT.

Other Reference:

Thank you for reading, pls keep visiting this blog and share this in your network. Also, I would love to hear your opinions down in the comments.

PS: If you found this content valuable and want to thank me? 👳 Buy Me a Coffee

Subscribe to our newsletter

Get the latest and greatest from Codepedia delivered straight to your inbox.


Post Comment

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

14 Comments