logo

,

JWT Authentication in Asp.net Core Web API

JSON Web Tokens (JWT) are Industry Standard tokens (RFC 7519). They are self contained and can contain Credentials, Claims and Other information. The structure of JWT is basically a long string. The string is divided into 3 parts and each part is separated by “.”. 

  • First Part – This is the header of the token. This contains information regarding the algorithm which is used to encrypt the signature and the  type of token.
  • Second Part – This is the Payload of the token. This contains information about our claims. For example User Id, User Role, Email Id, Token Expiry Date & Time Stamp, etc.
  • Third Part – This is the Signature of the token. This signature is encrypted by a secure key, which usually resides on the server.

The Signature is the only thing which is encrypted in the token, everything else is very easily obtained by simply decoding the token.

Below screenshot is the example of how JWT string look like

How JWT Authentication Works?

  1. The client will send username and password to the server.
  2. The server will validate the username and password provided by the client, create a JWT token and sends it back to the client.
  3. Client will now send the JWT token in all its further requests which requires authorization on the server.
  4. Server will validate the JWT send by the client and authorizes it. If the token is not provided by the client or the token is expired or the token is invalid the server will return Unauthorized response.

Implement JWT Authentication in Asp.net Core Web API Project.

Step 1 – Create Asp.net Core Web API Project.

Step 2 – Add an Interface ITokenService.cs in the Project.

    public interface ITokenService
    {
        string CreateToken(string username);
    }

Step 3 – Add a class TokenService.cs and implement the interface ITokenService

    public class TokenService : ITokenService
    {
        public string CreateToken(string username)
        {
            throw new NotImplementedException();
        }
    }

Step 4 – Update the TokenService.cs file as below.

Before updating this class please include all the below mentioned namespaces.

using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

The TokenService.cs file should be as below.

    public class TokenService : ITokenService
    {
        //Injecting IConfiguration into this class in order to read Token Key from the configuration file
        private readonly SymmetricSecurityKey _key;
        public TokenService(IConfiguration config)
        {
            _key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"]));
        }

        public string CreateToken(string username)
        {
            //Creating Claims. You can add more information in these claims. For example email id.
            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.NameId, username)
            };

            //Creating credentials. Specifying which type of Security Algorithm we are using
            var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);

            //Creating Token description
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(1),
                SigningCredentials = creds
            };

            var tokenHandler = new JwtSecurityTokenHandler();

            var token = tokenHandler.CreateToken(tokenDescriptor);

            //Finally returning the created token
            return tokenHandler.WriteToken(token);
        }
    }

Step 5 – Create an API Controller.

In this step we will be creating an API Controller by name AccountController.cs

Step 6 – Inject ITokenService Into AccountController

We will inject our ITokenService interface into our AccountController. This will allow us to access the CreateToken method. The AccountController should look like below at this stage.

    [Route("api/[controller]")]
    [ApiController]
    public class AccountController : ControllerBase
    {
        private readonly ITokenService _tokenService;
        public AccountController(ITokenService tokenService)
        {
            _tokenService = tokenService;
        }
    }

Step 7 – Create Login Action Method.

We will create Login Action Method or end point into our AccountController. The Login Action Method will accept username and password from the client. If provided username and password is valid, then a token is returned to the client. The Login Action Method should look like below.

        [HttpPost("login")]
        public ActionResult Login(string username, string password)
        {
            if (username != "admin" && password != "admin")
                return Unauthorized("Invalid Credentials");
            else
                return new JsonResult(new { userName = username, token = _tokenService.CreateToken(username) });
        }

Step 8 – Register ITokenService and TokenService.

In this step we will register our ITokenService interface and its implementation TokenService into our Startup.cs file, in order for it to be accessible throughout our application.
In case if you are using .Net 6 and above this registration has to be done in the program.cs file.
Read: What Happened to Startup.cs File in .Net 6?

Step 9 – Add the TokenKey.

Add the key “TokenKey” into our appsettings.Development.json. This key is used for encryption. This key was used in Step 4.

Step 10 – Test Login API from the Postman App.

Now as we are done with all the coding and configuration stuff, let us now test our Login action method (which is responsible to generate authentication token) in Postman App. You can test this API through swagger as well.

As expected, we are able to get our authentication token once we provide valid username and password.

You can decode the token string by following the below URL:

https://token.dev/

Send Request to Web API with JWT Token

Now we will create another controller by name TestController, and in this controller we will add two action methods, namely First and Second as shown below.

As you can see in the above screenshot, we have decorated our First action method with “AllowAnonymous” attribute, which means in order to access this action method or end point the client need not to be authenticated and authorized. Whereas we have decorated the Second action method with “Authorize” attribute, which means in order to access this action method the client need to be authenticated and authorized.

As our Second action method is decorated with “Authorize” attribute, this means it is expecting an authentication token from the client in the request. Let us try to send a request to Second end point with the token (which we generated by calling the login end point) in the header of this request.

 

As you can see we are receiving an error. This is because we haven’t registered our authentication middleware.

To register the authentication middleware, navigate to Startup.cs file (Program.cs file if you are using .Net 6 or above), and add the below code in the ConfigureServices method.

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
               .AddJwtBearer(options =>
               {
                   options.TokenValidationParameters = new TokenValidationParameters
                   {
                       ValidateIssuerSigningKey = true,
                       IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["TokenKey"])),
                       ValidateIssuer = false,
                       ValidateAudience = false,
                   };
               });

Add below code in the Configure method, just above app.UseAuthorization(). Ordering is important here.

 app.UseAuthentication();

Now, let us test our application again.

As expected, we are able to receive the response now from the Second action method or end point which is decorated by “Authorize” attribute.

What else you can do:

  1. Call the Second action method without the JWT token. You should receive Unauthorized error.
  2. Try to change the text in the token string and send the request again to the Second action method or end point. You should receive Unauthorized error, as the server verifies the received token in each request. If the provided token is modified/invalid the server will respond Unauthorized.
  3. Call the First action method or end point without the JWT token. It should give you response without any errors, as it is decorated with “AllowAnonymous” attribute.

 

Don’t forget to check out Learn Mobile App Development with .NET MAUI

 

Share on facebook
Share on twitter
Share on linkedin

Related articles