JWT Authentication in ASP.NET Core

Today in this article we will learn how to integrate JWT authentication in ASP.NET Core API for 2.2 or lower version.

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.

ASP.NET core 3.1 support

Please refer to the below article for ASP.NET Core 3.1 or 5.0 support,

Getting started

Create ASP.NET Core 2.2 API using CLI or Visual Studio IDE.

I have used a default project template to create a REST service. Once you execute this service default GET API will return below results,

Enable JWT Authentication scheme

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

JWT authentication is already built into .NET Core frameworks. You need to add below ‘using’ references to your module.

using Microsoft.AspNetCore.Authentication.JwtBearer

Now let’s see step by steps required for enabling JWT bearer scheme,

  • Please go to Startup.cs and add below line of code to ConfigServices() method to register JWT Authentication scheme.

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme);

Please add below line of code in Configure() method in Startup.cs

app.UseAuthentication();

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

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = Configuration["JwtToken:Issuer"],
                            ValidAudience = Configuration["JwtToken:Issuer"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtToken:SecuredKey"]))
                        };
                    });
        }

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

  • ValidateIssuer – Gets or sets a value indicating whether the Issuer should be validated. True means Yes validation required.
  • 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.
  • 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.
  • ValidAudience – Gets or sets a string that represents a valid audience that will be used to check against the token’s audience

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

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseAuthentication();
            app.UseMvc();
        }

Please make sure to add app.UseAuthentication() before app.UseMvc() in Configure() method in Startup.cs

So far so good!.

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)

blank

Let’s execute the API. You will start noticing Error 401: Unauthorized

blank

Now, this error is expected, as I have not supplied the valid JWT secured token yet.

We have performed below so far,

  1. We have enabled JWT authentication middleware in Startup.cs
  2. We have enabled [Authorize] attribute in Controller classes

So that means every request to API decorated with [Authorize] attribute will be honored when passed with a valid bearer token. We will now see below how to pass JWT token.

Configuration file

The configuration file used in this applications is as below.

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },

  "JwtToken": {
    "SecretKey": "SecretKeywqewqeqqqqqqqqqqqweeeeeeeeeeeeeeeeeee",
    "Issuer": "https://localhost:44378",
  }
}

Above Appsettings.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 .NET Core using Dependency Injection easily.

Getting JWT secured Token

JWT token will be generated using a simple process which is explained towards the end of this article separately.

Here let’ use the generated JWT token is as below,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjIyNjQ4MTgsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0Mzc4IiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNzgifQ.
gNlEt2dgPOYHVgGLU2OxzLIuvkPQ6rOeO6_qziKOSl4

Let’s execute the API to validate the authentication and see if it is working fine.

Invoking Secured method

Here I am using SOAP UI as a client to verify the token and invoke secured GET method. As shown below API response is successful.

blank

User should send Authorization header using the Bearer schema and Authorization header which should look like as below.

Authorization: Bearer <token>

HTTP Client helper classes can also be used to perform client-side call and get the token.

Generate JWT bearer Token pro-grammatically

JWT bearer token can be generated programmatically.

To keep it simple let’s add new Controller to the existing WebAPI with name AuthController.

Complete code is as below,

    [Route("api/[controller]")]
    public class AuthController : Controller
    {
        private readonly IConfiguration _config;

        public AuthController (IConfiguration config)
        {
            _config = config;
        }

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

      

Above the API responds to an HTTP POST request and expects an object containing a username and password (a LoginModel object).

  private string BuildToken()
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtToken:SecretKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(_config["JwtToken:Issuer"],
              _config["JwtToken:Issuer"],
              expires: DateTime.Now.AddMinutes(30),
              signingCredentials: creds);

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

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

            if (login.Username == "thecodebuzz" && login.Password == "dont-tell-anyone")
            {
                validUser = true;
            }
            return validUser;
        }

        public class LoginModel
        {
            public string Username { get; set; }
            public string Password { get; set; }
        }

    }

So one can use IWA (Integrated windows authentication) and validate the user credential against LDAP if required.

Login model as JSON input as below,

{
 "UserName":"thecodebuzz",
 "Password":"dont-tell-anyone"
}

Now let’s invoke the POST method. I am using SOAP UI as client.

blank

The generated token is as below,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjIyOTUyOTEsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0Mzc4IiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNzgifQ.d9RU8K-6AcCzponANSTuKbRVyAW2a6IH7ZEsC2wMXr0

Use this generated token and go back to Step “Invoking Secured method “

Do you have any comments or ideas or any better suggestions to share?

Please sound off your comments below.

Happy Coding !!

References:

Summary

Security is an integral part of application development and today in this article we understood about JSON Web Token (JWT) and how to use JWT bearer token to secure .NET Core WebAPI in a few simple steps.



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



8 thoughts on “JWT Authentication in ASP.NET Core

Leave a Reply

Your email address will not be published. Required fields are marked *