JWT authentication in ASP.NET Core API

JWT authentication in ASP.NET Core API

Authentication is the process of verifying the identity of a user. It is very important because it makes the applications secure by permitting only authenticated users to access its protected resources.

To secure the .NET Core API, we can use a token-based mechanism. It involves attaching the token to every HTTP request as part of the headers and validating the token before allowing access to the resources.

Before implementing JWT token-based authentication, let's understand what is JWT token.

JSON Web token (JWT) is an open standard method for representing claims securely between two parties which are signed digitally using a secret (with HMAC algorithm) or public/private key pair using RSA or ECDSA algorithm.

Structure of JWT token

JWT tokens consist of three parts separated by dots(.), which are:

  1. Header

  2. Payload

  3. Signature

Below is a real example of a JWT token which is Base64Url encoded.

Header

The first part is the header. The header consists of two parts: the type of token and the signing algorithm used.

Payload

The second part of the token is the payload. It contains the claims which are statements about the entity and the additional data.

Signature

The third part is the signature. To create it you need to take the encoded header, encoded payload and a secret, the algorithm specified in the header and sign that.

The signature is used by the server to verify that it wasn't altered along the way.

Implementation

Now let's follow the below steps to configure the JWT authentication in the .NET Core API application.

  1. Install Microsoft.AspNetCore.Authentication.JwtBearer nuget package in the API project.

  2. Add the required JWT config key values in the appsettings.json file.

     "JwtSettings": {
         "Secret": "your-secret-key-here",
         "Issuer": "your-app",
         "ExpiryMinutes": 60,
         "Audience": "your-app"
       }
    
  3. In ASP.NET Core, the authentication is handled by the Authentication service, IAuthenticationService which is used by the authentication middleware. The authentication service uses authentication handlers to complete the authentication-related actions. The actions include:

    1) Authenticating a user.

    2) Responding when an unauthenticated user tries to access a secured resource.

    The registered authenticated handlers and their configuration options are called 'schemes'.

    Authentication schemes are used by registering the authenticating services in the program.cs. First, we need to call the AddAuthentication() method with the scheme JwtBearerDefaults.AuthenticationScheme and then call the AddJwtBearer extension method with the scheme and appropriate Jwt configuration settings as shown below.

    Add the below code in program.cs where we add services to the container.

     builder.Services.AddAuthentication(options =>
         {
             options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
             options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
         }).AddJwtBearer(options =>
         {
             options.TokenValidationParameters = new TokenValidationParameters
             {
                 IssuerSigningKey = new SymmetricSecurityKey (Encoding.ASCII.GetBytes(builder.Configuration["JwtSettings:Secret"])),
                 ValidateLifetime = true,
                 ValidateAudience = true,
                 ValidateIssuer = true,
                 ClockSkew = TimeSpan.Zero,
                 ValidIssuer = "https://localhost:5001",
                 ValidAudience = "https://localhost:5001",
                 ValidateIssuerSigningKey = true,
             };
         });
    
  4. Add the authentication middleware by calling UseAuthentication in program.cs file. Calling UseAuthentication registers the middleware that uses the previously registered authentication schemes. Call UseAuthentication before any middleware that depends on users being authenticated.

     var app = builder.Build();
     {
         app.UseExceptionHandler("/error");
         // Configure the HTTP request pipeline.
         app.UseHttpsRedirection();
         app.UseAuthentication();
         app.UseAuthorization();
         app.MapControllers();
         app.Run();
     }
    
  5. Secure the controllers/endpoints by adding the Authorize attribute from Microsoft.AspNetCore.Authorization namespace.

     using Microsoft.AspNetCore.Authorization;
     using Microsoft.AspNetCore.Mvc;
    
     namespace Api.Controllers
     {
         [Authorize]
         [ApiController]
         public class ProductsController : ControllerBase
         {
             //add methods here
         }
     }
    

Did you find this article valuable?

Support Sankarshan Ramesh by becoming a sponsor. Any amount is appreciated!