JWT Authentication in ASP.NET Core
ASP.NET Core separates authentication and authorization processes. This implementation demonstrates JSON Web Token (JWT) usage with essential components:
- Identity represents user identity
- Claim denotes individual credential attributes
- Policy defines authorization rules
Setup and Configuration
Install required package:
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
Configure services in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Authorization policies
services.AddAuthorization(options =>
{
options.AddPolicy("AdminAccess", policy =>
policy.RequireRole("Administrator"));
options.AddPolicy("SystemAccess", policy =>
policy.RequireRole("System", "Support"));
});
// JWT Authentication
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(configuration =>
{
configuration.RequireHttpsMetadata = false;
configuration.SaveToken = true;
configuration.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"]))
};
configuration.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception is SecurityTokenExpiredException)
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
Token Generation Endpoint
[HttpPost("authenticate")]
public IActionResult GenerateToken([FromBody] UserCredentials credentials)
{
if (credentials?.Username != "validUser" || credentials.Password != "validPass")
return Unauthorized();
var tokenClaims = new[]
{
new Claim(ClaimTypes.Name, credentials.Username),
new Claim(ClaimTypes.NameIdentifier, "user-123"),
new Claim(ClaimTypes.Role, "System")
};
var securityKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"]));
var signingCredentials = new SigningCredentials(
securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: Configuration["Jwt:Issuer"],
audience: Configuration["Jwt:Audience"],
claims: tokenClaims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: signingCredentials);
return Ok(new
{
accessToken = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
Protected Controller Example
[Authorize(Policy = "SystemAccess")]
[ApiController]
[Route("api/data")]
public class DataController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new[] { "Protected", "Resource", "Data" };
}
}
Key implemantation points:
- Authorizatoin middleware must precede endpoint routing
- Missing/invalid tokens return HTTP 401 status
- Unauthorized roles return HTTP 403 status
- Token expiration is automatically validated
Custom Authorization Handling
For custom authorization logic:
services.AddSingleton<IAuthorizationHandler, CustomPolicyHandler>();