JWT Authentication in ASP.NET Core
Today in this article we will learn how to integrate JWT authentication in ASP.NET Core API for 2.2 or lower version.
JSON Web Token( JWT) is an open standard used for securely transmitting information between parties as a JSON object. JSON Web Tokens are very useful for various scenarios like authorization purposes or Information exchange using digitally signed key-value pairs.
ASP.NET core 3.1 support
Please refer to the below article for ASP.NET Core 3.1 or 5.0 support,
Getting started
Create ASP.NET Core 2.2 API using CLI or Visual Studio IDE.
I have used a default project template to create a REST service. Once you execute this service default GET API will return below results,
Enable JWT Authentication scheme
Enabling JWT authentication in ASP.NET Core WebAPI is about registering the JWT Authentication middleware within the request pipeline.
JWT authentication is already built into .NET Core frameworks. You need to add below ‘using’ references to your module.
using Microsoft.AspNetCore.Authentication.JwtBearer
Now let’s see step by steps required for enabling JWT bearer scheme,
- Please go to Startup.cs and add below line of code to ConfigServices() method to register JWT Authentication scheme.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme);
Please add below line of code in Configure() method in Startup.cs
app.UseAuthentication();
The following is the final implementation of ConfigServices() method.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["JwtToken:Issuer"],
ValidAudience = Configuration["JwtToken:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtToken:SecuredKey"]))
};
});
}
TokenValidationParameters are explained as below. This is as per MSDN definition.
- ValidateIssuer – Gets or sets a value indicating whether the Issuer should be validated. True means Yes validation required.
- ValidateAudience – Gets or sets a boolean to control if the audience will be validated during token validation.
- ValidateLifetime – Gets or sets a boolean to control if the lifetime will be validated during token validation.
- ValidateIssuerSigningKey – Gets or sets a boolean that controls if validation of the SecurityKey that signed the securityToken is called.
- ValidIssuer – Gets or sets a String that represents a valid issuer that will be used to check against the token’s issuer.
- ValidAudience – Gets or sets a string that represents a valid audience that will be used to check against the token’s audience
The following is the final implementation of Configure() method.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
Please make sure to add app.UseAuthentication() before app.UseMvc() in Configure() method in Startup.cs
So far so good!.
Next step is to enable authentication using [Authorize] attribute as below. [Authorize] attribute can also be applied at the Controller level (if you need to secure all methods within a Controller)
Let’s execute the API. You will start noticing Error 401: Unauthorized
Now, this error is expected, as I have not supplied the valid JWT secured token yet.
We have performed below so far,
- We have enabled JWT authentication middleware in Startup.cs
- We have enabled [Authorize] attribute in Controller classes
So that means every request to API decorated with [Authorize] attribute will be honored when passed with a valid bearer token. We will now see below how to pass JWT token.
Configuration file
The configuration file used in this applications is as below.
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"JwtToken": {
"SecretKey": "SecretKeywqewqeqqqqqqqqqqqweeeeeeeeeeeeeeeeeee",
"Issuer": "https://localhost:44378",
}
}
Above Appsettings.json file has specified the values for the issuer, the audience and the signing key, and these key-value pairs will be accessible through the Configuration in .NET Core using Dependency Injection easily.
Getting JWT secured Token
JWT token will be generated using a simple process which is explained towards the end of this article separately.
Here let’ use the generated JWT token is as below,
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjIyNjQ4MTgsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0Mzc4IiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNzgifQ.
gNlEt2dgPOYHVgGLU2OxzLIuvkPQ6rOeO6_qziKOSl4
Let’s execute the API to validate the authentication and see if it is working fine.
Invoking Secured method
Here I am using SOAP UI as a client to verify the token and invoke secured GET method. As shown below API response is successful.
User should send Authorization header using the Bearer schema and Authorization header which should look like as below.
Authorization: Bearer <token>
HTTP Client helper classes can also be used to perform client-side call and get the token.
Generate JWT bearer Token pro-grammatically
JWT bearer token can be generated programmatically.
To keep it simple let’s add new Controller to the existing WebAPI with name AuthController.
Complete code is as below,
[Route("api/[controller]")]
public class AuthController : Controller
{
private readonly IConfiguration _config;
public AuthController (IConfiguration config)
{
_config = config;
}
[AllowAnonymous]
[HttpPost]
public IActionResult CreateToken([FromBody]LoginModel login)
{
if (login == null) return Unauthorized();
string tokenString = string.Empty;
bool validUser = Authenticate(login);
if (validUser)
{
tokenString = BuildToken();
}
else
{
return Unauthorized();
}
return Ok(new { Token = tokenString });
}
Above the API responds to an HTTP POST request and expects an object containing a username and password (a LoginModel object).
private string BuildToken()
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtToken:SecretKey"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(_config["JwtToken:Issuer"],
_config["JwtToken:Issuer"],
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
private bool Authenticate(LoginModel login)
{
bool validUser = false;
if (login.Username == "thecodebuzz" && login.Password == "dont-tell-anyone")
{
validUser = true;
}
return validUser;
}
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}
}
So one can use IWA (Integrated windows authentication) and validate the user credential against LDAP if required.
Login model as JSON input as below,
{
"UserName":"thecodebuzz",
"Password":"dont-tell-anyone"
}
Now let’s invoke the POST method. I am using SOAP UI as client.
The generated token is as below,
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjIyOTUyOTEsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0Mzc4IiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNzgifQ.d9RU8K-6AcCzponANSTuKbRVyAW2a6IH7ZEsC2wMXr0
Use this generated token and go back to Step “Invoking Secured method “
Do you have any comments or ideas or any better suggestions to share?
Please sound off your comments below.
Happy Coding !!
References:
Summary
Security is an integral part of application development and today in this article we understood about JSON Web Token (JWT) and how to use JWT bearer token to secure .NET Core WebAPI in a few simple steps.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
Very helpful and nicely explained.
Thank you SAM!
thank you,i am learning jwt knowledge form your blog.
Thanks Narojay. I am glad this article is helping you!
Thank you.I got it running.. Nicely explained.
I am glad, this article helped you. Thanks for the feedback Elijah!!
Finally I understood this post so I achieved it! thanks
Thanks Roger. Appreciate your comments and feedback!