JWT token authentication in asp.net core

In earlier post we have learned how to implement basic authentication in asp.net web api using AuthorizationFilterAttribute, which allow us to pass username, password with HttpActionContext object, so that we can perform basic security check for someone who is consuming our web api.

In this tutorial, you will learn how to implement JWT Token authentication in asp.net core web Api.

Now why we need JWT token! in some situation, just checking username and password is not enough for letting someone consume your api, you may need to check more authorization related information, there can be multiple parameters which will decide what type of information can be exposed to the caller.

JWT token is a JSON format, that allow us to set any number or parameters to check authentication and different level of authorization at the same time.

Web API JWT Token authentication example

Before we start implementing Web API Authentication using JWT token; let’s learn how to create a JWT token in C# in ASP.NET Core 3.1 Web Api application.

JWT is basically json web token authentication in asp.net core http context.

First you need to install Microsoft.AspNetCore.Authentication.JwtBearer package from Nuget Package manager

Create a secret (that needs to be at least 16 characters long)

string key="ABCDE-1234567890";
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));

Create a Claim array, add reference of System.Security.Claims;, You can add any number of claims as per authentication criteria requirement in business demand.

Claim[] claims = new Claim[] {
    new Claim(ClaimTypes.Name, "Arindam"),
    new Claim(JwtRegisteredClaimNames.Email, "webtrainingroom@gmail.com"),
    new Claim(JwtRegisteredClaimNames.Website, "webtrainingroom.com"),
    new Claim(JwtRegisteredClaimNames.AuthTime, DateTime.UtcNow.ToShortTimeString())
    };

Now create a JwtSecurityToken, add reference of System.IdentityModel.Tokens.Jwt;

var securityToken = new JwtSecurityToken(
        issuer: "WTR-OrderService Asp.net Core", //your app [optional]
        audience: "Any", //[optional]
        claims: claims,
        notBefore: DateTime.Now,
        expires: DateTime.Now.AddDays(1),
        signingCredentials: new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256)
    );

OR, You can also create the token without any additional parameter

var securityToken1 = new JwtSecurityToken(
        new JwtHeader(new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256)),
        new JwtPayload(claims));

Create the token string using JwtSecurityTokenHandler to be set in http header

string tokenString = new JwtSecurityTokenHandler().WriteToken(securityToken);

So, now if you write a function to get the JWT token, the code will look like example below.

string GetJwtToken()
{
            
    //a secret that needs to be at least 16 characters long
    var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MyProductionKeyTest123456"));
    Claim[] claims = new Claim[] {
        new Claim(ClaimTypes.Name, "Arindam"),
        new Claim(JwtRegisteredClaimNames.Email, "webtrainingroom@gmail.com"),
        new Claim(JwtRegisteredClaimNames.Website, "webtrainingroom.com"),
        new Claim(JwtRegisteredClaimNames.AuthTime, DateTime.UtcNow.ToShortTimeString())
    };
    var securityToken = new JwtSecurityToken(
        issuer: "WTR-OrderService Asp.net Core", //your app [optional]
        audience: "Any", //[optional]
        claims: claims,
        notBefore: DateTime.Now,
        expires: DateTime.Now.AddDays(1),
        signingCredentials: new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256)
    );          
           
    string tokenString = new JwtSecurityTokenHandler().WriteToken(securityToken);
    return tokenString;
}

Now you have seen how to create a JWT token, this token is created at consumer end, now we see how to receive the token at API end and retrieve value for authentication.

JWT token configuration in Startup file

First, we create a section called “AppKeys” (you can give any name) in apsettings.json file, these keys value will be required in JWT Token configuration, so we must make those keys easily configurable for different environment or clients.

"AppKeys": {
    "JwTSigningKey": "MyProductionKeyTest123456",
    "JwTIssuer": "WebTrainingRoom.Com",
    "JwTAudience": "All App"
  },

Now, to read the values from apsettings.json file I have created a class called AppKeys.cs like example below.

public class AppKeys
{        
    public string JwTSigningKey { get; set; }
    public string JwTIssuer { get; set; }
    public string JwTAudience { get; set; }
}

Then add the following lines in “ConfigureServices” method to read the section from json file.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppKeys>(Configuration.GetSection("AppKeys"));
    var appKeys = Configuration.GetSection("AppKeys").Get<AppKeys>();
}

Alternatively, you can avoid the above exercise, and read the value from appsettings.json just by Configuration["AppKeys:JwTSigningKey"]

Now we add some configuration changes in "ConfigureServices" method of Startup file, change the Token Validation Parameters as per your business need.

var appKeys = Configuration.GetSection("AppKeys").Get<AppKeys>();
var secretKey = Encoding.ASCII.GetBytes(appKeys.JwTSigningKey);
services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "JwtBearer";
        options.DefaultChallengeScheme = "JwtBearer";
    })
        .AddJwtBearer("JwtBearer", jwtBearerOptions =>
        {
            jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                ValidateIssuer = true,
                IssuerSigningKey = new SymmetricSecurityKey(secretKey),                        
                ValidIssuer = appKeys.JwTIssuer,
                ValidateAudience = true,
                ValidAudience = appKeys.JwTAudience,
                ValidateLifetime = true, //validate the expiration and not before values in the token
                ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
            };
        });

Make sure you have added Authentication in "Configure" Method.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// global cors policy
app.UseCors(x => x
        .AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader());
    app.UseAuthentication();
    app.UseAuthorization();
}

Learn more about JWT Validation and Authorization in ASP.NET Core

 
Web API JWT Token Authentication
Learn Web API: creating API using C# .Net, post, update, delete, read using .net API, set security, check authentication, testing.

C# web service interview questions

Learn API development
Asp.Net C# Web API Examples | Join Asp.Net MVC Course