Authenticate Asp.net core web API with JWT

Kailash Chandra Behera | Wednesday, October 25, 2023

Json web token which is also known as JWT is an international standard which is used to transfer data securely over internet for various purposes. Fore example you can use JWT token for authenticate, authorization etc. Here in this blog post, we will explore how to use the Json token.

Getting Started

Implementing Json web token in C# or asp.net core is very easy process, here we will demonstrate the following points.

  • Download Json Web Token (JWT).
  • Add JWT web token keys into configuration settings.
  • Register or configure JWS Token in project.
  • Generate a JWT token.
  • JWT authentication in action.
  • Enable Swagger for JWT Token Fields.
  • Decode JWT.

Download Json Web Token (JWT)

The JWT can be downloaded from Microsoft NuGet package. The below steps guide to download.

  • Go to your Solution Explorer and right click on the solution Explorer.
  • Click on the NuGet Package Manager and type jsonwebtoken in the search box of Browse tab.
  • List if libraries will be listed, select Microsoft.AspNetCore.Authentication.JwtBeare.
  • Click on the Install button on the right side of the pan.

Add JWT web token keys into configuration settings

Open the appsettings.json file, add the below settings at the end of the file by copying and pasting. These settings are JWTsecret and will help you to generate or decode tokens.

 ,  
  "JWT": {  
   "Key": "Yh2k7QSu4l8CZg5p6X3Pna9L0Miy4D3Bvt0JVr87UcOj69Kqw5R2Nmf4FWs03Hdx",  
   "Issuer": "JWTAuthenticationServer",  
   "Audience": "JWTServicePostmanClient",  
   "Subject": "JWTServiceAccessToken"  
  }  

Register or configure JWS Token in project

After adding keys in appsetting.json file for token, we need to register the JWT into project. To do this, we need to register a JWT authentication schema by using "AddAuthentication" method. The below codes describe, how to configure JWT authentication into project.

 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)  
 .AddJwtBearer(options =>  
  {  
    options.TokenValidationParameters = new TokenValidationParameters  
    {  
      ValidateIssuer = true,  
      ValidateAudience = true,  
      ValidateLifetime = true,  
      ValidateIssuerSigningKey = true,  
      ValidIssuer = builder.Configuration["Jwt:Issuer"],  
      ValidAudience = builder.Configuration["Jwt:Audience"],  
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))  
    };  
  });  

Generate a JWT token

The following code in signin method(one of the endpoint of api used to signin user and responsed token) describes how to generate token. The token will be generated as string and this string value will be sent to the client as response.

 [HttpPost("signin")]  
 public string Signin(Credential credential)  
 {  
      if (credential != null)  
      {  
           Guid guid = Guid.NewGuid();  
           string token = guid.ToString();  
           int result = this.userAccess.Signin(credential, token);  
           if (result > 0)  
           {  
                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.configuration["JWT:Key"]));  
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);  
                List<Claim> claims = new List<Claim>();  
                claims.Add(new Claim("User", credential.UserName));  
                claims.Add(new Claim("UserType", result.ToString()));  
                claims.Add(new Claim("token", token));  
                claims.Add(new Claim("Subject", this.configuration["JWT:Subject"]));  
                var tokeOptions = new JwtSecurityToken(issuer: this.configuration["JWT:Issuer"], audience: this.configuration["JWT:Audience"], claims: claims, expires: DateTime.Now.AddMinutes(6), signingCredentials: signinCredentials);  
                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);  
                return tokenString;  
           }  
           else  
                return "Invalid user";  
      }  
      else  
           return "Invalid credential";  
 }  

JWT authentication in action

To authenticate an endpoint before invoking by router, add the [Authorize] attribute above the action of controller like below.

 [Authorize(AuthenticationSchemes = Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)]  
 public Profile GetProfile()  
 {  
 }  

In the above code, when cliet reqests to GetProfile API, the rauter first will verify whether the token is exists with reqest header or not. If the token not available in request then routher will throw with 402 response code.

Enable Swagger for JWT Token Fields

Bydefault the JWT token field will appear in the swagger. after adding above configuratation, we need to add below codes for jwt standard fields. Find the builder.Services.AddSwaggerGen() in the programm file and replace with below code.

 builder.Services.AddSwaggerGen(c =>  
 {  
   c.SwaggerDoc("v1", new OpenApiInfo { Title = "FMN", Version = "v1" });  
   c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()  
   {  
     Name = "Authorization",  
     Type = SecuritySchemeType.ApiKey,  
     Scheme = "Bearer",  
     BearerFormat = "JWT",  
     In = ParameterLocation.Header,  
     Description = "JWT Authorization header using the Bearer scheme."  
     });  
 });  

JWT Token Decode

The following code are for JWT token dectypion. The jwt.decode method only decodes the token and should only every be used on trusted messages. Since jwt.verify also decodes the token after verification, it provides a safer and more secure way to decode the token, so it should be the preferred method.

 void JWTDecode()  
     {  
       var handler = new JwtSecurityTokenHandler();  
       //jwt io  
       var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", string.Empty);  
       //Request.Headers["Authorization"];  
       //jwtsecretKey  
       var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.configuration["JWT:Key"]));  
       var validations = new TokenValidationParameters  
       {  
         ValidateIssuerSigningKey = true,  
         IssuerSigningKey = secretKey,  
         ValidIssuer = this.configuration["JWT:Issuer"],  
         ValidAudience = this.configuration["JWT:Issuer"]  
       };  
       ////jwt io :JWT token decode   
       JwtSecurityToken jwtSecurityToken = handler.ReadJwtToken(token);  
     }  

JWT Structure

Header

JWT Header identifies which algorithm is used to generate the signature. You may notice JWT HS256 in Signin method is used which indicates that this token is signed using HMAC-SHA256.

Payload

JWTPayload contains the claims, the claims are additional data that can kept with token. Ther are three types of claims those are registered, public and private claims.

Signature

Securely validates the token. The signature is calculated by encoding the header and payload using Base64url Encoding RFC 4648 and concatenating the two together with a period separator. That string is then run through the cryptographic algorithm specified in the header.

Summary

Using JWT we can implement Authentication and Authorization in API as well as web applications. I hope the above of this blog post will be helpful to you.

Thanks


No comments: