Introduction
Microsoft released .NET 6.0 in November 2021. I have already written a couple of articles about JWT authentication on C# Corner. Since .NET 6.0 made some significant changes, I have decided to write one article about JWT authentication using .NET 6.0 version. We will be using the Microsoft Identity framework to store user and role information.
Authentication is the process of validating user credentials, and authorization is the process of checking privileges for a user to access specific modules in an application. In this article, we will see how to protect an ASP.NET Core Web API application by implementing JWT authentication. We will also see how to use authorization in ASP.NET Core to supply access to various functionalities of the application. We will store user credentials in an SQL server database, and we will use Entity Framework and Identity framework for database operations.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
In its compact form, JSON Web Tokens consist of three parts separated by dots (.), which are.
- Header
- Payload
- Signature
Therefore, a JWT typically looks like the following.
xxxx.yyyy.zzzz
Please refer to the link below for more details about JSON Web Tokens. Introduction to JWT
Create ASP.NET Core Web API using Visual Studio 2022
We need Visual Studio 2022 to create .NET 6.0 applications. We can choose the ASP.NET Core Web API template from Visual Studio 2022.

We can give a suitable name for our project and choose the .NET 6.0 framework.

Our new project will be created in a few moments.
We must install the 4 libraries below into the new project.
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.AspNetCore.Identity.EntityFrameworkCore
- Microsoft.AspNetCore.Authentication.JwtBearer
You can use the NuGet package manager to install the above packages.
We can change the appsettings.json with values below. It has database connection details and other details for JWT authentication.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ConnStr": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=JWTAuthDB;Integrated Security=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
},
"JWT": {
"ValidAudience": "http://localhost:4200",
"ValidIssuer": "http://localhost:5000",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
}
}
We can create a new folder, “Auth” and create the “ApplicationDbContext” class under Auth folder and add below code. We will add all the classes related to authentication under the Auth folder.
ApplicationDbContext.cs
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace JWTAuthentication.NET6._0.Auth
{
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
}
Create a static class “UserRoles” and add below values.
UserRoles.cs
namespace JWTAuthentication.NET6._0.Auth
{
public static class UserRoles
{
public const string Admin = "Admin";
public const string User = "User";
}
}
We have added two constant values “Admin” and “User” as roles. You can add as many roles as you wish.
Create class “RegisterModel” for new user registration.
RegisterModel.cs
using System.ComponentModel.DataAnnotations;
namespace JWTAuthentication.NET6._0.Auth
{
public class RegisterModel
{
[Required(ErrorMessage = "User Name is required")]
public string? Username { get; set; }
[EmailAddress]
[Required(ErrorMessage = "Email is required")]
public string? Email { get; set; }
[Required(ErrorMessage = "Password is required")]
public string? Password { get; set; }
}
}
Create class “LoginModel” for user login.
LoginModel.cs
using System.ComponentModel.DataAnnotations;
namespace JWTAuthentication.NET6._0.Auth
{
public class LoginModel
{
[Required(ErrorMessage = "User Name is required")]
public string? Username { get; set; }
[Required(ErrorMessage = "Password is required")]
public string? Password { get; set; }
}
}
We can create a class “Response” for returning the response value after user registration and user login. It will also return error messages if the request fails.
Response.cs
namespace JWTAuthentication.NET6._0.Auth
{
public class Response
{
public string? Status { get; set; }
public string? Message { get; set; }
}
}
We can create an API controller “AuthenticateController” inside the “Controllers” folder and add below code.
AuthenticateController.cs
using JWTAuthentication.NET6._0.Auth;
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 JWTAuthentication.NET6._0.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthenticateController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IConfiguration _configuration;
public AuthenticateController(
UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager,
IConfiguration configuration)
{
_userManager = userManager;
_roleManager = roleManager;
_configuration = configuration;
}
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (user != null && await _userManager.CheckPasswordAsync(user, model.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));
}
var token = GetToken(authClaims);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
[HttpPost]
[Route("register")]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
var userExists = await _userManager.FindByNameAsync(model.Username);
if (userExists != null)
return StatusCode(StatusCodes.Status500InternalServerError, new Response { Status = "Error", Message = "User already exists!" });
IdentityUser user = new()
{
Email = model.Email,
SecurityStamp = Guid.NewGuid().ToString(),
UserName = model.Username
};
var result = await _userManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
return StatusCode(StatusCodes.Status500InternalServerError, new Response { Status = "Error", Message = "User creation failed! Please check user details and try again." });
return Ok(new Response { Status = "Success", Message = "User created successfully!" });
}
[HttpPost]
[Route("register-admin")]
public async Task<IActionResult> RegisterAdmin([FromBody] RegisterModel model)
{
var userExists = await _userManager.FindByNameAsync(model.Username);
if (userExists != null)
return StatusCode(StatusCodes.Status500InternalServerError, new Response { Status = "Error", Message = "User already exists!" });
IdentityUser user = new()
{
Email = model.Email,
SecurityStamp = Guid.NewGuid().ToString(),
UserName = model.Username
};
var result = await _userManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
return StatusCode(StatusCodes.Status500InternalServerError, new Response { Status = "Error", Message = "User creation failed! Please check user details and try again." });
if (!await _roleManager.RoleExistsAsync(UserRoles.Admin))
await _roleManager.CreateAsync(new IdentityRole(UserRoles.Admin));
if (!await _roleManager.RoleExistsAsync(UserRoles.User))
await _roleManager.CreateAsync(new IdentityRole(UserRoles.User));
if (await _roleManager.RoleExistsAsync(UserRoles.Admin))
{
await _userManager.AddToRoleAsync(user, UserRoles.Admin);
}
if (await _roleManager.RoleExistsAsync(UserRoles.Admin))
{
await _userManager.AddToRoleAsync(user, UserRoles.User);
}
return Ok(new Response { Status = "Success", Message = "User created successfully!" });
}
private JwtSecurityToken GetToken(List<Claim> authClaims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return token;
}
}
}














ArturPosted Mar 27, 2024, 3:45 PM
Example with Clear Architecture could be good. For example, in which layer we put auth logic?
Chirag ParmarPosted Dec 12, 2023, 7:01 AM
Great example,working
Chirag ParmarPosted Dec 12, 2023, 7:00 AM
Great Example very simple explaination
Soumyakanta RoutPosted Nov 23, 2023, 11:16 AM
You shoud add the Update Database that is to be written on console
Valeria MoralesPosted Dec 5, 2022, 4:17 PM
Hi, great article. Do you know how to consume this with an NET Core MVC Project? Thanks
Robert MinardiPosted Nov 13, 2022, 9:14 PM
Great tutorial, this is exactly what I was looking for. Now I can add JWT authentication to my api project
Sertunc SELENPosted Nov 9, 2022, 10:40 AM
You save my life.
vaibhav shahPosted Jul 27, 2022, 2:46 PM
How does verification of taken will happen ?What will happen when we logout or token expires ?
Ccorner guptaPosted Jul 11, 2022, 6:03 AM
How the token get verified?
Prince OwusuPosted Jul 3, 2022, 9:42 AM
How do you log out?
Анатолий ДудиевPosted May 18, 2022, 7:12 AM
How can I make it work in MVC but instead of returning token return view?
Eren SöğütPosted Apr 17, 2022, 3:34 PM
Thank you very much to your post. I worked it with Visual studio Preview2022 in Mac. But I can not get rid of 401 error. As I checked everythink is exactly same with the above. I successfully getting the token via login, just tried to reach authorized controller and then getting 401. I wish having debugging the authorize filter. Tracing log just said: [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
Gareth DohertyPosted Apr 15, 2022, 11:20 PM
Sarathlal Saseendran do you have another post about how to extend the Identity user to include other fields? I'd like to add in FirstName, Surname amongst other things. This was a great post by the way.
sagar chardePosted Apr 13, 2022, 7:24 PM
Thank you so much, this article is very helpful. One thing I didn't understand, how the roles are getting inserted in [AspNetRoles] table.
Mansoor AhmedPosted Apr 10, 2022, 10:55 PM
Can You Please Provide Database Script. In Downloads.
Mansoor AhmedPosted Apr 10, 2022, 10:50 PM
Its Really Nice To See The Example. But I Don't Have SQLSERVER - Instead Of SQLSERVER . I Have SQLServer Express. And Using And Using SQL Management Studio. I am Getting Error. Of Migration Builder. Can You Help Build The DATABASE.
Adiyatumur TsPosted Apr 5, 2022, 6:00 AM
Hi, I got a problem. I done all good (register, login, db migration etc) but i can't get data WeatherForeCast with Authorize attribute. What is problem? Please help me. (Error is 401 not authorized)
Greivin Cruz RíosPosted Apr 4, 2022, 3:41 PM
Thank you Sir, I got error 500 "message": "User creation failed! Please check user details and try again."
John MurielPosted Mar 30, 2022, 5:48 PM
Postman and Swagger are both giving an Internal Server Error when trying to register new user
Wallyson JNPosted Mar 3, 2022, 4:51 AM
O melhor tutorial sobre .NET JWT que j? l?.
Adam HillPosted Feb 16, 2022, 4:30 PM
Hi Sarathlal ; it's well explained topic ! thanks , I have a question : can I add authentication type individual users while creating the project and inject Jwt with it ?
syed qadriPosted Feb 14, 2022, 8:00 PM
Hey Sarathlal, thanks for the explanation, I'm getting invalidsignature error when implementing it, may u can help!
Serdar GünaydınPosted Feb 5, 2022, 11:03 AM
Thanks Satarhlal that was the what i need
Luke VincentPosted Feb 1, 2022, 10:34 PM
And your passion shows! This was a 100% clear and delightfully helpful article on JWT for .Net 6.0 !! Thanks for this Sarathlal !