JWT Token Based Implementation using ASP.NET Core Web API

JSON Web Tokens (JWT) are used for securely transmitting information between parties as a JSON object. JWT is typically used for authentication and authorization. In this article, I'll walk you through how to implement JWT authentication in an ASP.NET Core Web API.

Steps to Implement JWT Token-Based Authentication
 

Create an ASP.NET Core Web API Project

  1. Open Visual Studio and create a new project.
  2. Select ASP.NET Core Web API template.
  3. Configure the project as per your requirements and click Create

Install Required NuGet Packages

  1. To implement JWT, you will need the following NuGet package.
  2. Microsoft.AspNetCore.Authentication.JwtBearer
  3. Install it via NuGet Package Manager
  4. 3. Configure JWT in appsettings.json
  5. In your appsettings.json, configure the JWT settings.
    {
      "JwtSettings": {
        "SecretKey": "wvFwnwxh7GucmY898kQdKzEU5TjE18SQ",  // Use a strong secret key
        "Issuer": "yourdomain.com",
        "Audience": "yourdomain.com",
        "ExpiryInMinutes": 60
      }
    }

Create a JWT Helper Class

Create a helper class that will be responsible for generating the JWT token.

public class JwtTokenHelper
{
    private readonly IConfiguration _configuration;

    public JwtTokenHelper(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GenerateToken(string username)
    {
        var secretKey = Encoding.ASCII.GetBytes(_configuration["JwtSettings:SecretKey"]);
        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, username)
            }),
            Expires = DateTime.UtcNow.AddMinutes(int.Parse(_configuration["JwtSettings:ExpiryInMinutes"])),
            Issuer = _configuration["JwtSettings:Issuer"],
            Audience = _configuration["JwtSettings:Audience"],
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }
}

Configure JWT Authentication in Startup.cs or Program.cs.

In Program.cs, you need to configure JWT authentication in the builder. Services and middleware pipeline. Here's the step-by-step process.

using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    // Add the JWT Bearer definition to Swagger
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n " +
                      "Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\n" +
                      "Example: \"Bearer 12345abcdef\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                },
                Scheme = "oauth2",
                Name = "Bearer",
                In = ParameterLocation.Header
            },
            new List<string>()
        }
    });
});

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

Steps to Configure Swagger to Pass JWT Tokens

Install-Package Swashbuckle.AspNetCore

Ensure you have Swashbuckle.AspNetCore is installed in your project.

dotnet add package Swashbuckle.AspNetCore

Create Login Endpoint

You can then create a Login endpoint inside a controller to issue JWT tokens.

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly JwtTokenHelper _jwtTokenHelper;

    public AuthController(JwtTokenHelper jwtTokenHelper)
    {
        _jwtTokenHelper = jwtTokenHelper;
    }

    [AllowAnonymous]
    [HttpPost("login")]
    public IActionResult Login([FromBody] LoginModel loginModel)
    {
        // For example, this is a simple check, replace it with actual user validation
        if (loginModel.Username == "test" && loginModel.Password == "password")
        {
            var token = _jwtTokenHelper.GenerateToken(loginModel.Username);
            return Ok(new { Token = token });
        }
        return Unauthorized();
    }
}

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

Protecting Routes

Finally, you can protect specific routes by adding the [Authorize] attribute in your controllers.

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get([FromQuery] int days)
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Testing JWT in Postman

  1. Login: Send a POST request to /api/auth/login with a valid username and password.
  2. Token: Copy the token from the login response.
  3. Protected Resource: Access the /API/WeatherForecast endpoint and include the JWT in the Authorization header:

Step 1. Obtain a JWT Token in Swagger.

  1. Create a Login Request
    • Open Postman and create a new request.
    • Set the request type to POST.
    • Enter the URL for your login endpoint (e.g., http://localhost:5000/api/auth/login).
  2. Set the Request Body
    • In the Body tab, select raw and set the format to JSON.
    • Enter the login credentials. For example
      {
          "username": "your-username",
          "password": "your-password"
      }
      Auth
  3. Send the Request
  4. Click the Send button.
  5. If the credentials are valid, you should receive a response containing the JWT token. The response might look like this.
    Send button
  6. Copy the token from the login response.
  7. Create a GET request for a protected route.
  8. Set Authorization to Bearer Token and paste the JWT.

Example

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InRlc3QiLCJuYmYiOjE3Mjk3Nzc1MDcsImV4cCI6MTcyOTc4MTEwNywiaWF0IjoxNzI5Nzc3NTA3LCJpc3MiOiJ5b3VyZG9tYWluLmNvbSIsImF1ZCI6InlvdXJkb21haW4uY29tIn0.ZOwHBIvd2wnjIW3NFOKRSc7QUkiQ2kybEc0yiYMfeN4

Send the request and check the response.

Summary

We have implemented JWT (JSON Web Token) authentication to enhance security and streamline user authentication in our application.