JSON Web Tokens (JWT) are one of the most popular ways to secure APIs. When combined with ASP.NET Core Identity and Entity Framework Core (EF), they provide a powerful and flexible authentication system for modern web applications.
In this article, youโll learn how to:
Set up ASP.NET Core Identity with EF Core
Configure JWT token authentication
Generate and validate JWTs in an API
Secure your endpoints with [Authorize]
๐งฉ What is JWT (JSON Web Token)?
A JWT is a compact, URL-safe token used to securely transmit information between parties.
It consists of three parts:
header.payload.signature
Example JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiJ2aXBpbi5taXR0YWxAZ21haWwuY29tIiwiaWF0IjoxNjk2MDE0MzQ3LCJleHAiOjE2OTYwMTc5NDd9.
3nwbOScm9vPh3O4uH0MknhrK5hLbAwT7LM0I9_rM9w4
Each part represents:
Header โ algorithm & token type
Payload โ user data (claims)
Signature โ verifies token integrity
๐ Reference:
JWT.io โ Introduction to JWT
โ๏ธ Step 1. Create a New ASP.NET Core Web API Project
dotnet new webapi -n JwtAuthApi
cd JwtAuthApi
๐งฑ Step 2. Add Required NuGet Packages
Run these commands:
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
๐๏ธ Step 3. Configure ApplicationDbContext
Create a new folder Data โ ApplicationDbContext.cs :
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace JwtAuthApi.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
}
}
๐ค Step 4. Register Identity and JWT in Program.cs
using JwtAuthApi.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// 1๏ธโฃ Configure EF Core
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// 2๏ธโฃ Add Identity
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// 3๏ธโฃ Configure JWT Authentication
var jwtKey = builder.Configuration["Jwt:Key"];
var jwtIssuer = builder.Configuration["Jwt:Issuer"];
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 = jwtIssuer,
ValidAudience = jwtIssuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
};
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
๐งพ Step 5. Add Configuration in appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=JwtAuthDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Jwt": {
"Key": "ThisIsASecretKeyForJwtToken12345",
"Issuer": "https://localhost:5001"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"AllowedHosts": "*"
}
๐ Step 6. Create Authentication Controller
Create Controllers/AuthController.cs :
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace JwtAuthApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IConfiguration _config;
public AuthController(UserManager<IdentityUser> userManager, IConfiguration config)
{
_userManager = userManager;
_config = config;
}
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
var user = new IdentityUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
return BadRequest(result.Errors);
return Ok("User registered successfully");
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = GetToken(authClaims);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
private JwtSecurityToken GetToken(List<Claim> authClaims)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
return new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: creds
);
}
}
public class RegisterModel
{
public string Email { get; set; } = "";
public string Password { get; set; } = "";
}
public class LoginModel
{
public string Email { get; set; } = "";
public string Password { get; set; } = "";
}
}
๐ง Step 7. Protect an API Endpoint
Create a test controller Controllers/TestController.cs :
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace JwtAuthApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[Authorize]
[HttpGet("secure")]
public IActionResult SecureEndpoint()
{
return Ok("You have accessed a protected endpoint!");
}
[AllowAnonymous]
[HttpGet("public")]
public IActionResult PublicEndpoint()
{
return Ok("Anyone can access this endpoint.");
}
}
}
Now when you access:
๐งช Step 8. Test Using Swagger or Postman
Register user
POST โ /api/auth/register
{ "email": "[email protected]", "password": "Test@123" }
Login user
POST โ /api/auth/login
โ Copy the returned JWT token.
Authorize
๐ก๏ธ Bonus. Role-Based Authorization
You can also decorate your API actions like:
[Authorize(Roles = "Admin")]
public IActionResult AdminOnly()
{
return Ok("Only admins can access this.");
}
To assign roles:
await _userManager.AddToRoleAsync(user, "Admin");
๐งพ Conclusion
By integrating ASP.NET Core Identity , Entity Framework , and JWT , you can create a modern, secure, and scalable authentication system suitable for web and mobile APIs.
It combines database-backed identity management with stateless token-based access.