In modern web applications, security is critical—especially when dealing with user data, financial transactions, or any form of sensitive operations. JSON Web Tokens (JWT) provide a stateless and scalable solution for authentication, while role-based authorization ensures users can only access what they're permitted to.
In this article, we’ll walk through how to implement JWT-based authentication and role-based authorization in an ASP.NET Core Web API.
🔧 Prerequisites
Before we begin, make sure you have:
🛠 Step 1. Create a New ASP.NET Core Web API Project
dotnet new webapi -n JwtAuthDemo
cd JwtAuthDemo
📦 Step 2. Install Required NuGet Packages
Install the following NuGet package for JWT support:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
🧩 Step 3. Configure JWT Authentication in Program.cs
Add the following JWT configuration to Program.cs
:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add Authentication services
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 = "your-app",
ValidAudience = "your-app",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSuperSecretKey123"))
};
});
// Add Authorization
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication(); // Must come before UseAuthorization
app.UseAuthorization();
app.MapControllers();
app.Run();
🛡 Replace "YourSuperSecretKey123"
with a secure key and store it in a secure place, such as Azure Key Vault or environment variables.
🔐 Step 4. Generate JWT Tokens
Create a service or endpoint to generate JWT tokens. Example:
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel login)
{
if (login.Username == "admin" && login.Password == "password") // Replace with real validation
{
var claims = new[]
{
new Claim(ClaimTypes.Name, login.Username),
new Claim(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSuperSecretKey123"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "your-app",
audience: "your-app",
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token)
});
}
return Unauthorized();
}
}
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}
🧾 Step 5. Secure Your Endpoints with Role-Based Authorization
In your controller, protect routes using the [Authorize]
attribute and specify roles:
[ApiController]
[Route("api/[controller]")]
public class AdminController : ControllerBase
{
[HttpGet("dashboard")]
[Authorize(Roles = "Admin")]
public IActionResult GetDashboard()
{
return Ok("Welcome to the admin dashboard!");
}
}
✅ Step 6. Test Your API
-
POST to /api/auth/login
with valid credentials
{
"username": "admin",
"password": "password"
}
-
Receive a JWT token in response.
-
Include the token in the Authorization header:
Authorization: Bearer {your-token}
Access protected routes like /api/admin/dashboard
.
🔒 Best Practices
-
Never hardcode secrets: use environment variables or secret managers.
-
Set token expiration: always use short-lived tokens.
-
Use HTTPS: always encrypt traffic.
-
Use Refresh Tokens: for long-lived sessions.
-
Validate claims: especially roles and permissions.
-
Log authentication failures: for monitoring and alerting.
🧠 Conclusion
JWT-based authentication with role-based authorization offers a flexible and scalable way to secure your ASP.NET Core Web APIs. Whether you're building an internal API or a public-facing application, this architecture keeps your endpoints secure and your users' data protected.
Let me know if you'd like to extend this with refresh tokens, custom claims, policy-based authorization, or integration with Identity Server / ASP.NET Core Identity.