.NET 7 Web API πŸ”’ JWT Authentication and role-based Authorization

R M Shahidul Islam Shahed
4 min readMar 28

--

A step-by-step guide to user authentication using ASP.NET Core 7, Identity, MSSQL
Create a minimal API project in Visual Studio 2022.
πŸ’» GitHub: https://github.com/shahedbd/API.UserManagement

JWT (JSON Web Token) authentication is a popular method of implementing authentication and authorization in modern web applications. In ASP.NET Core, JWT authentication is built into the framework and can be easily configured in your application.

After completing this guide you will have created an ASP.NET 7 web API that exposes a secure endpoint. The secure endpoint can only be accessed by users who have a registered account in your system.

πŸš€ Table of Contents:
βœ… 1. Create Project: Using Visual Studio 2022
- API Project, Dotnet 7.0, and a class library project for data connectivity and migration

βœ… 2. Install the Required Packages
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer β€” version 7.0.4
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore β€” version 7.0.4
dotnet add package Microsoft.EntityFrameworkCore.SqlServer β€” version 7.0.4
dotnet add package Microsoft.EntityFrameworkCore.Tools β€” version 7.0.4

βœ… 3. Database connection: MSSQL: appsettings.json
βœ… 4. Create models and complete ApplicationDbContext class
βœ… 5. Update program.cs: AddDbContext
βœ… 6. Database Migration
dotnet ef migrations add InitialCreate
dotnet ef database update
β€” using PMC
PM: add-migration initcreate
PM: update-database

βœ… 7. Create Auth Controller
βœ… 8. Crete Auth Service

βœ… 9. Test API using postman
βœ… 10. Deploy to IIS
βœ… 11. Test API from IIS hosting

Auth Service

public class AuthService : IAuthService
{
private readonly UserManager<ApplicationUser> userManager;
private readonly RoleManager<IdentityRole> roleManager;
private readonly IConfiguration _configuration;
public AuthService(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IConfiguration configuration)
{
this.userManager = userManager;
this.roleManager = roleManager;
_configuration = configuration;

}
public async Task<(int,string)> Registeration(RegistrationModel model,string role)
{
var userExists = await userManager.FindByNameAsync(model.Username);
if (userExists != null)
return (0, "User already exists");

ApplicationUser user = new()
{
Email = model.Email,
SecurityStamp = Guid.NewGuid().ToString(),
UserName = model.Username,
FirstName = model.FirstName,
LastName = model.LastName,
};
var createUserResult = await userManager.CreateAsync(user, model.Password);
if (!createUserResult.Succeeded)
return (0,"User creation failed! Please check user details and try again.");

if (!await roleManager.RoleExistsAsync(role))
await roleManager.CreateAsync(new IdentityRole(role));

if (await roleManager.RoleExistsAsync(role))
await userManager.AddToRoleAsync(user, role);

return (1,"User created successfully!");
}

public async Task<(int,string)> Login(LoginModel model)
{
var user = await userManager.FindByNameAsync(model.Username);
if (user == null)
return (0, "Invalid username");
if (!await userManager.CheckPasswordAsync(user, model.Password))
return (0, "Invalid password");

var userRoles = await userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};

foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
string token = GenerateToken(authClaims);
return (1, token);
}


private string GenerateToken(IEnumerable<Claim> claims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWTKey:Secret"]));
var _TokenExpiryTimeInHour = Convert.ToInt64(_configuration["JWTKey:TokenExpiryTimeInHour"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = _configuration["JWTKey:ValidIssuer"],
Audience = _configuration["JWTKey:ValidAudience"],
//Expires = DateTime.UtcNow.AddHours(_TokenExpiryTimeInHour),
Expires = DateTime.UtcNow.AddMinutes(1),
SigningCredentials = new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256),
Subject = new ClaimsIdentity(claims)
};

var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}

Application DB Context

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{

}
}

appsettings.json

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"connMSSQLNoCred": "Server=DESKTOP-99Q87I2\\MSSQLSERVER2017;Database=APIUserManagement;Trusted_Connection=True;MultipleActiveResultSets=true",
"connMSSQL": "Server=DESKTOP-99Q87I2\\MSSQLSERVER2017;Database=APIUserManagement;User ID=sa;Password=dev123456;MultipleActiveResultSets=true;TrustServerCertificate=True"
},
"JWTKey": {
"ValidAudience": "https://localhost:5001",
"ValidIssuer": "https://localhost:5001",
"TokenExpiryTimeInHour": "3",
"Secret": "ecawiasqrpqrgyhwnolrudpbsrwaynbqdayndnmcehjnwqyouikpodzaqxivwkconwqbhrmxfgccbxbyljguwlxhdlcvxlutbnwjlgpfhjgqbegtbxbvwnacyqnltrby"
},
"AllowedHosts": "*"
}

Configure Identity and JWT

// For Identity  
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Adding Authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})

// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = builder.Configuration["JWTKey:ValidAudience"],
ValidIssuer = builder.Configuration["JWTKey:ValidIssuer"],
ClockSkew = TimeSpan.Zero,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWTKey:Secret"]))
};
});

Overall, JWT authentication provides a secure and efficient way to authenticate and authorize users in ASP.NET Core applications. It is widely used in modern web development and can be easily configured in ASP.NET Core.

Congratulations on making it this far! Really good job.
You have now created a secure API endpoint only accessible by authenticated users who have a valid JWT token. As well as the functionality for users to sign up and to login.

πŸš€ Main Profile

βœ… Business ERP Solution/Product/POS/Company Management

βœ… School/College/University Management ERP

βœ… Dashboard Template | ASP.NET Core MVC Web Starter Kit

βœ… Advance POS System with Stock Manager | ASP.NET Core | EF Core | .NET Core 6.0

βœ… Asset Management System with Barcode | ASP.NET Core | EF Core | .NET Core 6.0

βœ… Advanced Files & Users Management | ASP.NET Core | EF Core | .NET Core | MSSQL | MySQL

βœ… Hospital and Pharmacy Management System | ASP.NET Core | EF Core:
https://1.envato.market/OR5o6N

βœ… Inventory and User Management System

βœ… Invoice Gen(Invoice Generation and Management) using .Net Core and EF

βœ… Complaint | Issue | Helpdesk Ticket | My Ticket HelpDesk Support System | ASP.NET Core | EF Core

βœ… User Management

βœ… ASP.NET Core CRUD Operation Using Dot Net 6.0 | MVC| MSSQL | MySQL | EF Core Code First | jQuery

βœ… ASP.NET Core full CRUD with .NET 5 | MSSQL/MySQL | EF code first:
https://1.envato.market/OR551W

βœ… Staff | Employee Leave Management System

βœ… Library Management System | ASP.NET Core | MSSQL | Code First

--

--

R M Shahidul Islam Shahed

.NET Developer, Author at Codecanyon