Authentication & Authorization with JWT in ASP.NET Core

Securing your API isn’t optional; it’s essential. In this post, we’ll walk through how to implement JWT (JSON Web Token) authentication in ASP.NET Core so your API knows who’s calling, and what they’re allowed to do.


🔐 What is JWT?

JWT stands for JSON Web Token a compact, URL-safe way of representing claims between two parties.

A JWT looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

It’s composed of:

  • Header
  • Payload (claims)
  • Signature

The server issues a token after login, and the client sends it with every request.


🛠️ Step 1: Install JWT Authentication NuGet Package

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

⚙️ Step 2: Configure JWT in Program.cs

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "yourapp.com",
            ValidAudience = "yourapp.com",
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes("your-super-secret-key"))
        };
    });

builder.Services.AddAuthorization();

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

Store your secret in appsettings.json or a secure vault in production.


🔑 Step 3: Generate a Token After Login

[HttpPost("login")]
public IActionResult Login(UserLoginModel model)
{
    // Fake validation
    if (model.Username != "admin" || model.Password != "password")
        return Unauthorized();

    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.UTF8.GetBytes("your-super-secret-key");

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Name, model.Username),
            new Claim(ClaimTypes.Role, "Admin")
        }),
        Expires = DateTime.UtcNow.AddHours(1),
        Issuer = "yourapp.com",
        Audience = "yourapp.com",
        SigningCredentials = new SigningCredentials(
            new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

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

🔒 Step 4: Protect Your Endpoints

[Authorize]
[HttpGet("secure-data")]
public IActionResult GetSecureData()
{
    return Ok("Only logged-in users can see this");
}

Or restrict to specific roles:

[Authorize(Roles = "Admin")]
public IActionResult GetAdminOnlyData() => Ok("Admins only");

🧪 Testing in Swagger

To test secured endpoints in Swagger:

  1. Add app.UseAuthentication() before UseAuthorization()
  2. Configure Swagger to accept JWT headers (optional)
  3. Pass your token via Bearer Token in Postman or Swagger UI

✅ Up Next

Your API is now protected! Up next: how to log, trace, and recover from errors using Serilog and global error handling middleware.

➡️ Error Handling & Logging with Serilog →

Security first. Let’s keep shipping 🚀

0
Subscribe to my newsletter

Read articles from Esanju Babatunde directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Esanju Babatunde
Esanju Babatunde