How to implement JWT authentication in ASP.NET Core

By FoxLearn 12/31/2024 9:27:49 AM   243
Securing minimal API endpoints in ASP.NET Core using JSON Web Tokens (JWT) for authentication and authorization is straightforward.

Minimal APIs are designed for building lightweight HTTP APIs, making them ideal for microservices. Securing these endpoints often involves adding JWT authentication to ensure that only authorized users can access certain parts of your API.

Steps to Secure Minimal API Endpoints with JWT Authentication

Begin by creating a new ASP.NET Core Web API project using Visual Studio 2022. In the "Create new project" window, select "ASP.NET Core Web API" and ensure that you don’t select "Use controllers," as we’ll be working with minimal APIs.

Create an API Endpoint

In the Program.cs file, create a simple HTTP GET endpoint. Use .RequireAuthorization() to enforce that authentication is required to access this endpoint.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/secure/hello", () => "Hello, Secure World!").RequireAuthorization();
app.Run();

Install JWT Authentication Package

Next, Add the Microsoft.AspNetCore.Authentication.JwtBearer NuGet package to the project.

Alternatively, you can install the package by using the NuGet Package Manager console and entering the following command.

PM> Install-Package Microsoft.AspNetCore.Authentication.JwtBearer

Next, create a section in the appsettings.json file to store the Issuer, Audience, and Key values, which will be used to generate a JSON Web Token.

Add the following information to your appsettings.json file:

"JwtSettings": {
  "Issuer": "https://example.com/",
  "Audience": "https://example.com/",
  "Key": "YourSecureSecretKeyHere1234"
}

Configure JWT Authentication

In the Program.cs file, configure the JWT authentication middleware. This will specify the settings for JWT validation, including the secret key, issuer, and audience.

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

To add authorization services to your application, include the following code snippet in your Program.cs file:

builder.Services.AddAuthorization();

Add User Model

Create a User model class to hold login credentials.

public class User
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

This class will be used to authenticate users.

JWT Token Generation Endpoint

Create an HTTP POST endpoint to generate JWT tokens when a user provides valid credentials.

app.MapPost("/secure/login", [AllowAnonymous] (User user) =>
{
    if (user.UserName == "testuser" && user.Password == "password123")
    {
        var token = GenerateJwtToken(user);
        return Results.Ok(token);
    }
    return Results.Unauthorized();
});

This endpoint checks the user’s username and password, and if they are correct, generates and returns a token.

Generate JWT Token

Implement the GenerateJwtToken method to create a signed JWT token using the JwtSecurityTokenHandler class.

private string GenerateJwtToken(User user)
{
    var issuer = builder.Configuration["Jwt:Issuer"];
    var audience = builder.Configuration["Jwt:Audience"];
    var key = Encoding.ASCII.GetBytes(builder.Configuration["Jwt:Key"]);

    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
    };

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddMinutes(30),
        Issuer = issuer,
        Audience = audience,
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

Use Authentication and Authorization

Ensure that the authentication and authorization middleware is added to the pipeline. This ensures that requests are authenticated before accessing secure endpoints.

app.UseAuthentication();
app.UseAuthorization();

Once the API is set up, you can use tools like Postman to test it. First, use the login endpoint (/secure/login) to obtain a JWT. Then, include the token as a Bearer token in the Authorization header when calling the /secure/hello endpoint. If the token is valid, the API will return the secured message.

Example of the login request:

  • POST: /secure/login
  • Body (JSON): { "UserName": "testuser", "Password": "password123" }

Example of the secured endpoint request:

  • GET: /secure/hello
  • Authorization: Bearer <JWT Token>

In this example, we’ve shown how to secure minimal API endpoints using JWT in ASP.NET Core. The process involves setting up JWT authentication, creating an endpoint for token generation, and securing other API routes.