How to Implement JWT Authentication in C# Web API
This article provides a straightforward guide on implementing JSON Web Token (JWT) authentication and bearer token validation in an ASP.NET Core Web API. You will learn which NuGet packages to install, how to store configuration settings, how to configure the authentication middleware in your application pipeline, how to generate a token, and how to secure API endpoints using authorization attributes.
1. Install the Required NuGet Package
To validate JWTs, install the
Microsoft.AspNetCore.Authentication.JwtBearer package via
the .NET CLI or the NuGet Package Manager:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer2. Configure
Token Settings in appsettings.json
Define your token parameters in appsettings.json. The
secret key must be sufficiently long (at least 256 bits / 32 characters)
to satisfy cryptographic requirements.
{
"Jwt": {
"Key": "YourSuperSecretKeyWithSufficientLength32CharactersLong!",
"Issuer": "https://yourdomain.com",
"Audience": "https://yourdomain.com",
"DurationInMinutes": 60
}
}3. Register
Authentication Services in Program.cs
Add the authentication service and configure the JWT Bearer validation options. This tells the application how to inspect and validate incoming tokens.
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var jwtSettings = builder.Configuration.GetSection("Jwt");
var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]!);
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = true;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true,
ValidIssuer = jwtSettings["Issuer"],
ValidateAudience = true,
ValidAudience = jwtSettings["Audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseHttpsRedirection();
// Place UseAuthentication before UseAuthorization
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();4. Generate the JWT Bearer Token
Create a method or an authentication endpoint to validate user credentials and issue a signed token containing user claims.
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IConfiguration _configuration;
public AuthController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
// Replace with actual database user verification
if (request.Username != "testuser" || request.Password != "password123")
{
return Unauthorized("Invalid credentials.");
}
var jwtSettings = _configuration.GetSection("Jwt");
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Key"]!));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, request.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Role, "User")
};
var token = new JwtSecurityToken(
issuer: jwtSettings["Issuer"],
audience: jwtSettings["Audience"],
claims: claims,
expires: DateTime.UtcNow.AddMinutes(double.Parse(jwtSettings["DurationInMinutes"]!)),
signingCredentials: credentials);
return Ok(new
{
Token = new JwtSecurityTokenHandler().WriteToken(token)
});
}
}
public record LoginRequest(string Username, string Password);5. Secure
Endpoints with the [Authorize] Attribute
Apply the [Authorize] attribute to controllers or action
methods to restrict access to requests containing a valid JWT.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class DataController : ControllerBase
{
[HttpGet]
public IActionResult GetSecureData()
{
var username = User.Identity?.Name;
return Ok(new { Message = $"Access granted for {username}." });
}
}Clients must include the token in the Authorization
header formatted as Bearer <your-token> when making
requests to protected endpoints. In response, ASP.NET Core will validate
the token against the defined TokenValidationParameters
before granting access.