DEV Community

Sabir Sheikh
Sabir Sheikh

Posted on

πŸ” Building JWT Authentication in ASP.NET Core (Step-by-Step)

In modern web applications, JWT (JSON Web Token) is a powerful and widely used technique for securing APIs. This guide will walk you through how to implement JWT authentication in an ASP.NET Core MVC project using a practical controller and configuration example.

🧱 Prerequisites

  • .NET Core SDK installed
  • Visual Studio or VS Code
  • Basic understanding of ASP.NET Core
  • NuGet packages:
Microsoft.AspNetCore.Authentication.JwtBearer
Enter fullscreen mode Exit fullscreen mode
System.IdentityModel.Tokens.Jwt
Enter fullscreen mode Exit fullscreen mode

🎯 Project Overview

We are building a simple API that:

  • Accepts login credentials
  • Generates a JWT token if the credentials are correct
  • Provides a protected endpoint (TestApi2) accessible only with a valid token

πŸ›  Step 1: Configure JWT in Startup.cs

πŸ” ConfigureServices– JWT Setup

public void ConfigureServices(IServiceCollection services)
{
    string securityKey = "Your256BitSecretKeyWhichNeedsToBe32BytesLong!"; // Must be 32 bytes
    var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "myshop.com.in",
                ValidAudience = "user",
                IssuerSigningKey = symmetricSecurityKey
            };
        });

    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Enter fullscreen mode Exit fullscreen mode

βœ… Key points:

  • The securityKey must be 32 bytes when using HMAC SHA-256.
  • The token is validated based on Issuer, Audience, and SigningKey.

πŸ” Configure– Middleware

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseAuthentication(); // πŸ” Add JWT Authentication middleware
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Enter fullscreen mode Exit fullscreen mode

βœ… Important: app.UseAuthentication() must be called before UseMvc().

πŸ“¦ Step 2: Create JWT Controller

Here’s a breakdown of your TestJWTController.

[HttpPost]
public IActionResult GetToken()
{
    string securityKey = "Your256BitSecretKeyWhichNeedsToBe32BytesLong!";
    var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
    var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: "myshop.com.in",
        audience: "user",
        expires: DateTime.Now.AddHours(1),
        signingCredentials: signingCredentials
    );

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

Enter fullscreen mode Exit fullscreen mode

πŸ” /GetToken Endpoint
This endpoint generates a JWT token signed with your securityKey.
The token is valid for 1 hour.

*πŸ§ͺ /Login Endpoint (Dummy Authentication)
*

[HttpPost]
public string Login([FromBody] LoginModel login)
{
    if (login.Username == "sabir" && login.Password == "sabir")
    {
        return "Success";
    }
    return "Unauthorized";
}

Enter fullscreen mode Exit fullscreen mode
  • Simple login check with hardcoded credentials.
  • In a real-world app, validate against a database.

*πŸ”“ /TestApi – Public Endpoint
*

[HttpPost]
public string TestApi()
{
    byte[] key = new byte[16];
    using (var rng = new RNGCryptoServiceProvider())
    {
        rng.GetBytes(key);
    }

    return Convert.ToBase64String(key);
}

Enter fullscreen mode Exit fullscreen mode
  • Generates a 128-bit random key.
  • This API is accessible without authentication.

*πŸ” /TestApi2 – Protected with [Authorize]
*

[HttpPost]
[Authorize]
public string TestApi2()
{
    byte[] key = new byte[16];
    using (var rng = new RNGCryptoServiceProvider())
    {
        rng.GetBytes(key);
    }

    return "Auth" + Convert.ToBase64String(key);
}

Enter fullscreen mode Exit fullscreen mode

You must send a valid JWT token in the Authorization header to access this.

Example:

Authorization: Bearer <your_token_here>

Enter fullscreen mode Exit fullscreen mode

πŸ“¦ LoginModel Class

Used to bind JSON payload during login:

public class LoginModel
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Testing the Flow

1. Get Token
POST /TestJWT/GetToken
β†’ Returns JWT token

2. Access Unprotected API
POST /TestJWT/TestApi
β†’ Always works

3. Access Protected API
POST /TestJWT/TestApi2 with Header:
Authorization: Bearer
β†’ Returns response only if token is valid

βœ… Final Thoughts

  • πŸ”’ JWT is great for securing APIs in stateless applications.
  • 🚫 Do not hardcode credentials or secrets in production.
  • πŸ›‘ Always store JWT secret keys in a secure config like Azure Key Vault or AWS Secrets Manager.
  • πŸ‘¨β€πŸ’» Use middleware and services to centralize token handling and validation.

Top comments (0)