ASP.NET Core  

JWT Authentication with ASP.NET Core Identity and Entity Framework (EF)

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:

  • GET /api/test/public โ†’ works for everyone

  • GET /api/test/secure โ†’ requires a valid JWT

๐Ÿงช Step 8. Test Using Swagger or Postman

  1. Register user
    POST โ†’ /api/auth/register

          
            { "email": "[email protected]", "password": "Test@123" }
          
        
  2. Login user
    POST โ†’ /api/auth/login
    โ†’ Copy the returned JWT token.

  3. Authorize

    • In Swagger, click Authorize โ†’ paste Bearer {token} .

    • Call /api/test/secure โ†’ โœ… Success!

๐Ÿ›ก๏ธ 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.