What is JWT Token?
JSON Web Token is a JSON based access token which is signed by one private key or one party and the party will be able to verify the token. It is safe and compact. JWT is a JSON object that has the capacity to transmit information between multiple parties.
Its structure consists of Header, Payload, and Signature.
The header contains two parts which are encoded by base64 format.
- {
- "alg" : "HS256",
- "typ" : "JWT"
- }
The payload is basic information that we wanted to send to the client, like login user information.
- {
- "name" : "admin",
- "code" : "adm12873",
- }
The signature is basically used for validating the message and another responsibility of signature is whether the token contains authentic information or not. The signature is encoded by Base64url Encoding.
- HMAC-SHA256(
- base64urlEncoding(header) + '.' +
- base64urlEncoding(payload),
- secret
- )
ASP.NET Core Token Authentication and Authorization using JWT
In ASP.NET Core controller handles all the HTTP requests/ routes and each route has been called by the client to perform the action required.
We need to secure the controller using JWT by [Authorize] attribute. That is why we need some configuration to register a JWT.
- public void ConfigureServices(IServiceCollection services) {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
- var appSettingsSection = Configuration.GetSection("AppSettings");
- services.Configure < KeySettings > (appSettingsSection);
- var appSettings = appSettingsSection.Get < KeySettings > ();
- var key = Encoding.ASCII.GetBytes(appSettings.SecretKey);
- services.AddAuthentication(x => {
- x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
- }).AddJwtBearer(x => {
- x.RequireHttpsMetadata = false;
- x.SaveToken = true;
- x.TokenValidationParameters = new TokenValidationParameters {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = new SymmetricSecurityKey(key),
- ValidateIssuer = false,
- ValidateAudience = false
- };
- });
- services.AddScoped < IUserService, UserService > ();
- }
As we know, in appsettings.json configuration is kept by the form of key-value pairs. We need to provide a configuration for SecretKey.
- {
- "AppSettings": {
- "SecretKey": "WQW79-OFFKDI940NG7-56753253-SADVF-5769-0921-DSD987987SA"
- },
- "Logging": {
- "LogLevel": {
- "Default": "Warning"
- }
- }
- }
After application settings, we need to Configure User Authentication service by using app.UseAuthentication().
Startup.cs
- public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
- app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
- app.UseAuthentication();
- app.UseMvc();
- }
In the above code, you can see the app.UseCors() method, we are using this method to Allow any Origin. We will discuss what Cross-Origin Request (CORS) is later.
How to Generate JSON Web Token in ASP.NET Core?
Here I have introduced a JWTController. This Controller will invoke the IsValidate() method for user validation and that method will generate the JWT token, I have decorated my action methods [HttpPost("token")] and it allows an Anonymous call by using [AllowAnonymous] attribute.
- using JwtToken.Model;
- using JwtToken.Services;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Mvc;
- namespace JwtToken.Controllers {
- [Authorize]
- public class JWTController: ControllerBase {
- IUserValidationService _uservalidationService;
- public JWTController(IUserValidationService uservalidationService) {
- this._uservalidationService = uservalidationService;
- }
- [AllowAnonymous]
- [HttpPost("token")]
- public IActionResult Authenticate([FromBody] UserEntity userParam) {
- var user = this._uservalidationService.IsValidate(userParam.Username, userParam.Password);
- if (user == null) {
- return BadRequest(new {
- message = "UserName or Password is invalid"
- });
- }
- return Ok(user);
- }
- }
- }
In here you can see the IsValidate() method that will validate and return JWT.
UserValidationService.cs
- using System;
- using System.Collections.Generic;
- using System.IdentityModel.Tokens.Jwt;
- using System.Linq;
- using System.Security.Claims;
- using System.Text;
- using JwtToken.HelperService;
- using JwtToken.Model;
- using Microsoft.Extensions.Options;
- using Microsoft.IdentityModel.Tokens;
- namespace JwtToken.Services {
- public class UserValidationService: IUserValidationService {
- List < UserEntity > users;
- KeySettings key;
- public UserValidationService(IOptions < KeySettings > appSettings) {
- this.key = appSettings.Value;
- this.users = new List < UserEntity > {
- new UserEntity {
- Id = 1, FirstName = "Sachin", LastName = "Tendulkar", Email = "[email protected]", Username = "sachin", Password = "123"
- }
- };
- }
- public UserEntity IsValidate(string username, string password) {
- var user = users.SingleOrDefault(x => x.Username == username && x.Password == password);
- if (user == null) {
- return null;
- }
- var key = Encoding.ASCII.GetBytes(this.key.SecretKey);
- var jwtToken = new SecurityTokenDescriptor {
- Subject = new ClaimsIdentity(new Claim[] {
- new Claim(ClaimTypes.Name, user.Id.ToString())
- }),
- Expires = DateTime.UtcNow.AddDays(10),
- SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
- };
- var tokenHandler = new JwtSecurityTokenHandler();
- var token = tokenHandler.CreateToken(jwtToken);
- user.Token = tokenHandler.WriteToken(token);
- return user;
- }
- }
- }
In the above section, I have used hardcode data to test the user authentication. Here I have introduced SecurityTokenDescriptor class to decorate JWT Token, Claim Expires, and SigningCredentials.
How to Test the API?
To test the Web API, I am Using PostMan and the following JSON in the request body.
https://localhost:44392/token
POST
Content-Type : application/json
- {
- "username": "sachin",
- "password": "123"
- }
Based on the response, we will get the following JSON like.
- {
- "id": 1,
- "firstName": "Sachin",
- "lastName": "Tendulkar",
- "username": "sachin",
- "password": "123",
- "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjEiLCJuYmYiOjE1Njg5MjQ4NDQsImV4cCI6MTU2OTc4ODg0NCwiaWF0IjoxNTY4OTI0ODQ0fQ.YmXyHl4J-dY43nT96h-00E8Az7YWDECJon0ZLu6fjik",
- "email": "[email protected]"
- }
Now I am going to validate other Controller to see if the JWT is working for me or not. In here we need to pass the JWT like this way.
Conclusion
Authentication is the most essential part of any web application, specifically WEB API. Because your WEB API can consume any client. Microsoft has introduced OAuth 2.0 and the JSON Web Token (JWT). In this article, you learned about JWT as well as how to implement JWT by using ASP.NET Core.