Recently I come across a requirement to create .NET Core Web API using JWT (JSON Web Token) authentication. I have used ASP.NET identity to provide a role-based authentication model. I have used .NET core 3.x to create this example.
For the sake of simplicity, I have used the default .NET Core project template to create a simple project.
First of all, I have created a new project using the ASP.NET Core Web Application template.

Select the project location

Select the project template as “Web Application”. Select Authentication to “Individual user – Store in Application”

Now Visual Studio will create a new project with ASP.NET core identity authentication model. User accounts along with claims are stored in the database. If you run this project you will have the website with login and register functionality.

Now the next step is to create a Web API that uses the same users and generates a unique JWT token for authorization.
Create Login model to use for input parameters for API methods
public class LoginModel
{
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
I have created a new controller in the Controllers folder with the name “AuthController” and created a Login method in this controller. The purpose of this method is; when an API client provides a user name and password to the method this method will generate a token. see the following code snippet …
[ApiController]
[Route("Api/[controller]")]
public class AuthController : Controller
{
public class AuthenticationController : Controller
{
private UserManager<IdentityUser> _userManager;
//private readonly IEmailSender _emailSender; UnComment if you want to add Email Verification also.
public AuthenticationController(
UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Email)
}),
Issuer = "https://yourhostname.com",
Audience = "https://yourhostname.com",
Expires = DateTime.Now.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Key-From-Appsettings")), SecurityAlgorithms.HmacSha512Signature),
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return Ok(new
{
token = tokenHandler.WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
}
}
Now if you can access this API method through Postman. it will give you Jwt token like below

Now you can use this token to access any secure API controller. An example of a secure controller is below.
[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme, Roles = "ApiUser")]
[Route("Api/[controller]")]
[ApiController]
public class SecureController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
public SecureController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
[HttpGet]
[Route("GetUser")]
public async Task<IActionResult> GetMessageAsync()
{
var user = await GetCurrentUserAsync();
if (user != null)
{
return Ok(user);
}
return BadRequest("Error");
}
#region Helpers
private async Task<IdentityUser> GetCurrentUserAsync()
{
string userName = HttpContext.User.Identity.Name;
return await _userManager.FindByNameAsync(userName);
}
#endregion
}
The above example controller is only accessed by the user of the role “ApiUser”.