ASP.NET Core  

How to Implement JWT Authentication in ASP.NET Core

Introduction

JWT (JSON Web Token) authentication is one of the most popular and secure ways to protect APIs in ASP.NET Core. It is widely used in modern web applications, mobile apps, and microservices because it is stateless, scalable, and easy to integrate.

In simple words, JWT authentication allows users to log in once and then use a token to access protected resources without sending credentials again and again.

In this article, we will learn how to implement JWT authentication in ASP.NET Core step by step, using simple language, real examples, and best practices.

What is JWT (JSON Web Token)?

A JSON Web Token (JWT) is a compact and secure way to transmit information between parties as a JSON object.

A JWT consists of three parts:

  • Header → Contains algorithm and token type

  • Payload → Contains user data (claims)

  • Signature → Used to verify the token

Example format:

Header.Payload.Signature

Why Use JWT Authentication?

  • Stateless authentication (no server session required)

  • Scalable for large applications

  • Works well with APIs and microservices

  • Secure when implemented correctly

Step-by-Step Implementation of JWT Authentication in ASP.NET Core

Step 1: Create ASP.NET Core Web API Project

Create a new Web API project using Visual Studio or .NET CLI.

Step 2: Install Required NuGet Packages

Install the following package:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

Step 3: Add JWT Settings in appsettings.json

"Jwt": {
  "Key": "ThisIsASecretKeyForJWT",
  "Issuer": "YourApp",
  "Audience": "YourAppUsers",
  "DurationInMinutes": 60
}

Step 4: Configure JWT Authentication in Program.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

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.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtSettings["Issuer"],
        ValidAudience = jwtSettings["Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

builder.Services.AddAuthorization();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

Step 5: Create a JWT Token Service

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Text;

public class JwtService
{
    private readonly IConfiguration _config;

    public JwtService(IConfiguration config)
    {
        _config = config;
    }

    public string GenerateToken(string username)
    {
        var jwtSettings = _config.GetSection("Jwt");
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(ClaimTypes.Name, username)
        };

        var token = new JwtSecurityToken(
            issuer: jwtSettings["Issuer"],
            audience: jwtSettings["Audience"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(Convert.ToDouble(jwtSettings["DurationInMinutes"])),
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

Step 6: Create Login Endpoint

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly JwtService _jwtService;

    public AuthController(JwtService jwtService)
    {
        _jwtService = jwtService;
    }

    [HttpPost("login")]
    public IActionResult Login(string username, string password)
    {
        if (username == "admin" && password == "1234")
        {
            var token = _jwtService.GenerateToken(username);
            return Ok(new { Token = token });
        }

        return Unauthorized();
    }
}

Step 7: Protect API Endpoints

[Authorize]
[HttpGet("secure-data")]
public IActionResult GetSecureData()
{
    return Ok("This is protected data");
}

Step 8: Test the API

  • Call login API → Get JWT token

  • Add token in Authorization header

Authorization: Bearer your_token_here
  • Call secure API → Access granted

How JWT Authentication Works Internally

  1. User logs in with username/password

  2. Server validates credentials

  3. Server generates JWT token

  4. Client stores token

  5. Client sends token in every request

  6. Server validates token

  7. Access is granted

Best Practices for JWT Authentication

  • Keep secret key secure

  • Use HTTPS always

  • Set token expiration time

  • Use refresh tokens for long sessions

  • Avoid storing sensitive data in payload

Common Mistakes Developers Make

  • Hardcoding secret keys

  • Not validating token properly

  • Using long expiration times

  • Not using HTTPS

Real-World Use Cases

  • Web APIs authentication

  • Mobile app login systems

  • Microservices communication

  • Single Page Applications (SPA)

Summary

JWT authentication in ASP.NET Core is a powerful and scalable way to secure your APIs. It allows stateless authentication using tokens, improving performance and scalability. By following the correct implementation steps and best practices, you can build secure and modern applications using JWT.