Generate JWT Token and Authenticate

In this article we will learn how to generate fresh JWT secured token in ASP.NET Core with simple easy to understand examples.

Category Fundamentals | Tags: JWT Token, Authentication

Published: 27 October 2020

What is JWT

JSON Web Token( JWT) is an open standard used for securely transmitting information between parties as a JSON object. JSON Web Tokens are very useful for various scenarios like authorization purposes or Information exchange using digitally signed key-value pairs. Below is sample JWT token example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
eyJleHAiOjE1NzEwMDc3MzQsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0MzQxIiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDEifQ
Ve2x6ueiHPyrP7wLjpmZrhx7QWrQKnkxWsu_1qUKKLA

Getting started

We shall be creating a simple .NET Core service which will create JWT token programmatically for a given set of credentials. However, you can use any project type as needed.

Build the JWT Token

We shall be making use of class JwtSecurityToken for initializing new instances of token-based in parameters like Symmterickey, credentials, and expiry, etc.

Here I shall be making use above class within a .NET Core Controller so that we are able to expose an API endpoint for returning newly generated JWT token to the user.

Let’s define the configuration properties to be used for generating the JWT token. Here below is an example of a configuration we shall be used to generate the JWT.

"JwtToken": {
    "SecretKey": "SecretKeywqewqeqqqqqqqqqqqweeeeeeeeeeeeeeeeeeeqweqe",
    "Issuer": "https://localhost:44341",
    "Audience": "https://localhost:44341",
    "TokenExpiry": "60" //minutes
},


As above I have defined the properties to be used in class JwtSecurityToken.

  • SecretKey–  SigningCredentials with Secured algorithm and key that signs the security token.
  • Issuer – A valid issuer that will be used to check against the token’s issuer.
  • Audience – A valid audience that will be used to check against the token’s audience
  • TokenExpiry– Define the lifetime expiry of the token once issued from current date and timestamp

 Note: The secret key length should be a minimum of 128 bits i.e (16 bytes)

Below is the basic implementation of the custom BuildToken() method.

private string BuildJWTToken()
{
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtToken:SecretKey"]));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var issuer = _config["JwtToken:Issuer"];
    var audience = _config["JwtToken:Audience"];
    var jwtValidity = DateTime.Now.AddMinutes(Convert.ToDouble(_config["JwtToken:TokenExpiry"]));

    var token = new JwtSecurityToken(issuer,
    audience,
    expires: jwtValidity,
    signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

 

The above generic method can be used in any type of application like batch, or console, etc if needed. Lets now complete our Controller method using the above logic.

In the below implementation, I have added additional security on the Controller method to validate the user credentials requesting the new JWT token.

I have used the POST method so that login credentials can be sent before issuing the JWT token.

[AllowAnonymous]
[HttpPost]
public IActionResult CreateToken([FromBodyLoginModel login)
{
    if (login == nullreturn Unauthorized();
    string tokenString = string.Empty;
    bool validUser = Authenticate(login);
    if (validUser)
    {
        tokenString = BuildJWTToken();
    }
    else
    {
        return Unauthorized();
    }
    return Ok(new { Token = tokenString });
}

 

Below is the method to validate the user requesting new JWT token,

private bool Authenticate(LoginModel login)
{
    bool validUser = false;

    if (login.Username == _config["AuthLogin:UserName"
        && login.Password == _config["AuthLogin:Password"])
    {
        validUser = true;
    }
    return validUser;
}

 

LoginModel class is defined as below,

public class LoginModel
{
    public string Username { getset; }
    public string Password { getset; }
}


Now you can use the above token to secure your API to validate the authentication and see if it is working fine.

JWT Authentication example

We shall now cover below aspects of enabling JWT authentication in ASP.NET Core API,

  • Install the JWT middleware
  • Configure the JWT Bearer scheme
  • Securing an API
  • Generate JWT Token
  • Verifying Secured API Responses HttpStatus(200 and 401)

Enable JWT Authentication scheme

Enabling JWT authentication in ASP.NET Core WebAPI is about registering the JWT Authentication middleware within the request pipeline.

Please note that the JWT middleware component was built into .NET Core 2.2 frameworks previously. But ASP.NET Core 3.0 onwards it needs to be installed through the Nuget package separately.

 

NuGet Package Manager CLI

 

PM>Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 3.1.2

 

Now let’s see step by steps required for enabling JWT bearer scheme by adding the below using namespaces to use the same in the code,

using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;


In Startup.cs please update ConfigServices() method to register JWT Authentication scheme and use AddAuthentication() extension methods for setting up authentication services in a ServiceCollection as below.

Here we have set DefaultAuthenticateScheme as JwtBearerDefaults.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddCors();

    services.AddAuthentication(option =>
    {
        option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
   }).AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = false,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["JwtToken:Issuer"],
            ValidAudience = Configuration["JwtToken:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtToken:SecretKey"]))
        };
    });
}

 

You may want to set up the configuration accordingly if supporting multiple authentication scheme in the same API.

TokenValidationParameters are explained as below. This is as per the MSDN definition.

  • ValidateIssuerSigningKey – Gets or sets a boolean that controls if validation of the SecurityKey that signed the securityToken is called.
  • ValidIssuer – Gets or sets a String that represents a valid issuer that will be used to check against the token’s issuer.
  • ValidateIssuer – Gets or sets a value indicating whether the Issuer should be validated. True means Yes validation required.
  • ValidAudience – Gets or sets a string that represents a valid audience that will be used to check against the token’s audience.
  • ValidateAudience – Gets or sets a boolean to control if the audience will be validated during token validation.
  • ValidateLifetime – Gets or sets a boolean to control if the lifetime will be validated during token validation.

The following is the final implementation of the Configure() method.

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

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseCors(option => option
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());

    app.UseAuthentication();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

 

In the above example, CORS will be needed only if your API needs to be supporting cross-domain calls.

The next step is to enable authentication using [Authorize] attribute as below. [Authorize] attribute can also be applied at the Controller level (if you need to secure all methods within a Controller)

[HttpGet]
[Authorize]
public async Task<IEnumerable<string>> Get()
{
    var accessToken = await HttpContext.GetTokenAsync("access_token");

    return new string[] { accessToken };
}

 

Configure Secretes Key and Token

The configuration file used in applications is as shown below.

The appsetting.json file has specified the values for the issuer, the audience, and the signing key, and these key-value pairs will be accessible through the configuration in ASP.NET Core using Dependency Injection easily. One can supply required values through an Environment variable or YAML or Secrete Storage if any (if the host environment is Cloud etc.)

{
    "Logging": {
        "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "JwtToken": {
        "SecretKey": "xxxxxxxxxx...xx",
        "Issuer": "your issue address"
    }
}

 

There is a limitation of the SecretKey length used in the SymmetricSecurityKey before signing and generating the signed credentials. It’s recommended using a 128-bit key, generated with cryptographic algorithms as per RFC2104. For .NET/.NET Core, the key Secret key should be a minimum of 128 bits i.e (16 bytes).

Summary

Secured programming is not an afterthought process. It needs to be considered on the day first. It is an integral part of any application development and today in this article we understood how to create/generate JSON Web Token (JWT) token to secure .NET Core applications like WebAPI or other types in a few simple steps. We understood how to use the JWT bearer token to secure ASP .NET Core applications in a few easy steps. We also exposed this functionally as an API/Service so that it can be leveraged by other API or Applications.