Ad Code

✨🎆 JOIN MERN, JAVA, PYTHON, AI, DEVOPS, SALESFORCE Courses 🎆✨

Get 100% Placement Oriented Program CLICK to new more info click

What is JWT Authentication | How to apply in API in .NET Core

 This tutorial assumes you’re building an MVC app that also exposes APIs or wants token-based login.





🔹 Step 1: Create ASP.NET Core MVC Project

dotnet new mvc -n JwtAuthDemo cd JwtAuthDemo

🔹 Step 2: Install Required NuGet Packages

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer dotnet add package System.IdentityModel.Tokens.Jwt

🔹 Step 3: Add JWT Settings in appsettings.json

{ "Jwt": { "Key": "ThisIsMySecretKeyForJwt123!", "Issuer": "https://yourdomain.com", "Audience": "https://yourdomain.com", "ExpireMinutes": 30 }, "Logging": { "LogLevel": { "Default": "Information" } }, "AllowedHosts": "*" }

⚠️ Use a long, secure key (store it in User Secrets or Azure Key Vault in production).


🔹 Step 4: Configure JWT in Program.cs

using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; var builder = WebApplication.CreateBuilder(args); // 1. Add Controllers with Views builder.Services.AddControllersWithViews(); // 2. JWT Authentication Configuration 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) }; }); var app = builder.Build(); // Middlewares app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // Authentication & Authorization app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();

🔹 Step 5: Create a Model for Login

Models/LoginModel.cs

namespace JwtAuthDemo.Models { public class LoginModel { public string Username { get; set; } public string Password { get; set; } } }

🔹 Step 6: Create Token Service

Services/TokenService.cs

using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; namespace JwtAuthDemo.Services { public class TokenService { private readonly IConfiguration _config; public TokenService(IConfiguration config) { _config = config; } public string GenerateToken(string username, string role) { var jwtSettings = _config.GetSection("Jwt"); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Key"])); var claims = new[] { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role) }; var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: jwtSettings["Issuer"], audience: jwtSettings["Audience"], claims: claims, expires: DateTime.Now.AddMinutes(Convert.ToDouble(jwtSettings["ExpireMinutes"])), signingCredentials: creds ); return new JwtSecurityTokenHandler().WriteToken(token); } } }

🔹 Step 7: Create Authentication Controller

Controllers/AuthController.cs

using JwtAuthDemo.Models; using JwtAuthDemo.Services; using Microsoft.AspNetCore.Mvc; namespace JwtAuthDemo.Controllers { [ApiController] [Route("api/[controller]")] public class AuthController : ControllerBase { private readonly TokenService _tokenService; public AuthController(TokenService tokenService) { _tokenService = tokenService; } [HttpPost("login")] public IActionResult Login([FromBody] LoginModel login) { // ⚠️ Replace with real user validation (DB/Identity) if (login.Username == "admin" && login.Password == "123") { var token = _tokenService.GenerateToken(login.Username, "Admin"); return Ok(new { Token = token }); } return Unauthorized("Invalid credentials"); } } }

🔹 Step 8: Protect Your MVC Controllers

Example: Controllers/HomeController.cs

using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace JwtAuthDemo.Controllers { public class HomeController : Controller { [Authorize] public IActionResult Index() { return Content("Welcome! You are authenticated with JWT."); } [Authorize(Roles = "Admin")] public IActionResult AdminOnly() { return Content("Hello Admin! You have access."); } } }

🔹 Step 9: Test the Flow

  1. Run the project → https://localhost:5001/api/auth/login
    Send POST request with:

    { "username": "admin", "password": "123" }

    Response:

    { "token": "eyJhbGciOi..." }
  2. Use this token in Authorization Header:

    Authorization: Bearer eyJhbGciOi...
  3. Access https://localhost:5001/home/index → works only with valid JWT.
    Access https://localhost:5001/home/adminonly → works only if role is "Admin".

How to Handle with Database

Database → Login → Get Role → Generate JWT → [Authorize(Roles = "...")]

Your current GenerateToken(username, role) is already suitable. The main question is how to store and retrieve the role.

1. Simple approach: Role column in Users table

For your current requirement, you can keep it very simple:

CREATE TABLE Users
(
Id INT PRIMARY KEY IDENTITY(1,1),
Username VARCHAR(100) NOT NULL UNIQUE,
PasswordHash VARCHAR(500) NOT NULL,
Role VARCHAR(50) NOT NULL,
IsActive BIT NOT NULL DEFAULT 1
);

Example data:

IdUsernameRoleIsActive
1shivaAdmin1
2amitFaculty1
3rajFrontDesk1

2. During login, get the role from database

For example:

var user = await _context.Users
.FirstOrDefaultAsync(x => x.Username == username && x.IsActive);

if (user == null)
{
return Unauthorized();
}

After validating the password:

var token = GenerateToken(
user.Username,
user.Role
);

So if the database contains:

amit | Faculty

you automatically generate:

Username = amit
Role = Faculty

You don't need to manually decide the role in your controller.


3. Your GenerateToken stays almost the same

public string GenerateToken(string username, string role)
{
var jwtSettings = _config.GetSection("Jwt");

var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(jwtSettings["Key"])
);

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

var credentials = new SigningCredentials(
key,
SecurityAlgorithms.HmacSha256
);

var token = new JwtSecurityToken(
issuer: jwtSettings["Issuer"],
audience: jwtSettings["Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(8),
signingCredentials: credentials
);

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

4. Then authorization becomes very easy

Admin only

[Authorize(Roles = "Admin")]
public IActionResult CreateBatch()
{
return Ok("Admin allowed");
}

Faculty only

[Authorize(Roles = "Faculty")]
public IActionResult MarkAttendance()
{
return Ok("Faculty allowed");
}

Admin OR Faculty        

[Authorize(Roles = "Admin,Faculty")]
public IActionResult ViewBatch()
{
return Ok("Admin or Faculty allowed");
}    
Create Project

For your type of system

If you're building something like your student/batch/attendance management system,

I'd structure permissions roughly like:

SuperAdmin
Admin
Faculty
FrontDesk

But don't rely on this hierarchy automatically. Define access explicitly:

Dashboard
Admin ✅
Faculty ✅
FrontDesk ✅

Add Registration
Admin ✅
Faculty ❌
FrontDesk ✅

Create Batch
Admin ✅
Faculty ❌
FrontDesk ❌

Mark Attendance
Admin ✅
Faculty ✅
FrontDesk ❌

Delete Batch
Admin ✅
Faculty ❌
FrontDesk ❌
Another Task for Multiple Roles

Recommended design for a larger application

I'd recommend this structure for your application.

Users

CREATE TABLE Users
(
Id INT PRIMARY KEY IDENTITY(1,1),
Username VARCHAR(100) NOT NULL UNIQUE,
PasswordHash VARCHAR(500) NOT NULL,
IsActive BIT NOT NULL DEFAULT 1
);

Roles

CREATE TABLE Roles
(
Id INT PRIMARY KEY IDENTITY(1,1),
RoleName VARCHAR(50) NOT NULL UNIQUE
);

Insert:

INSERT INTO Roles (RoleName)
VALUES
('Admin'),
('Faculty'),
('FrontDesk');

UserRoles

CREATE TABLE UserRoles
(
UserId INT NOT NULL,
RoleId INT NOT NULL,

PRIMARY KEY (UserId, RoleId),

FOREIGN KEY (UserId) REFERENCES Users(Id),
FOREIGN KEY (RoleId) REFERENCES Roles(Id)
);

Now you can have:

Users
--------------------------------
1 | shiva
2 | amit
3 | raj
Roles
--------------------------------
1 | Admin
2 | Faculty
3 | FrontDesk

And:

UserRoles
--------------------------------
UserId | RoleId
1 | 1
2 | 2
3 | 3

So:

Shiva → Admin
Amit → Faculty
Raj → FrontDesk

7. Multiple roles become possible

Suppose Shiva needs both Admin and Faculty:

UserRoles
--------------------------------
UserId | RoleId
1 | 1
1 | 2

Now:

Shiva
├── Admin
└── Faculty

This is much more flexible.


8. Login query

You can retrieve all roles for the logged-in user:

var user = await _context.Users
.FirstOrDefaultAsync(x =>
x.Username == username &&
x.IsActive);

if (user == null)
{
return Unauthorized();
}

Then:

var roles = await _context.UserRoles
.Where(x => x.UserId == user.Id)
.Select(x => x.Role.RoleName)
.ToListAsync();

You might get:

roles =

Admin
Faculty

Then generate the JWT with multiple role claims.

var claims = new List<Claim>
{
new Claim(
ClaimTypes.NameIdentifier,
user.Id.ToString()
),

new Claim(
ClaimTypes.Name,
user.Username
)
};

foreach (var role in roles)
{
claims.Add(
new Claim(ClaimTypes.Role, role)
);
}

Now the JWT contains:

Name = Shiva
Role = Admin
Role = Faculty

And both work:

[Authorize(Roles = "Admin")]

and:

[Authorize(Roles = "Faculty")]

9. This is the architecture I recommend for you

Since you're building a system with Admin, Faculty and FrontDesk and likely want to add more roles later, use:

DATABASE
Users
UserRoles
Roles
Login
Generate JWT
┌────────┴────────┐
▼ ▼
Admin Faculty
│ │
└────────┬────────┘
API Controller
[Authorize(Roles)]

For example:

[Authorize(Roles = "Admin,Faculty")]
public IActionResult MarkAttendance()
{
// Admin OR Faculty
}

and:

[Authorize(Roles = "Admin")]
public IActionResult DeleteStudent()
{
// Admin only
}

Post a Comment

0 Comments