Code2night
  • Home
  • Blogs
  • Tutorial
  • Post Blog
  • Tools
    • Json Beautifier
    • Html Beautifier
  • Members
    • Register
    • Login
  1. Home
  2. Blogpost
29 Dec
2022

JWT Token Authentication And Authorizations In Web API

by Shubham Batra

767

Download Attachment

I will walk you through using the JWT token in your web API.net core project in this step-by-step tutorial. The following topics are covered in this tutorial.

  1. How to authorize any web API endpoint 
  2. How to create a JWT access token


Step 1. Install Nuget Packages

Then open Nuget Package manager and install the latest version of the following packages,

  • Microsoft.AspNetCore.Authentication.JwtBearer
  • Microsoft.IdentityModel.JsonWebTokens
  • System.IdentityModel.Tokens.Jwt

Step 2. Add Model and settings

Add a new folder to your project root directory named “Models” and a new class named “JwtSettings” and “UserTokens”.

JwtSettings.cs file,

 public class JwtSettings
    {
        public bool ValidateIssuerSigningKey { get; set; }
        public string IssuerSigningKey { get; set; }
        public bool ValidateIssuer { get; set; } = true;
        public string ValidIssuer { get; set; }
        public bool ValidateAudience { get; set; } = true;
        public string ValidAudience { get; set; }
        public bool RequireExpirationTime { get; set; }
        public bool ValidateLifetime { get; set; } = true;
    }

UserTokens.cs file

  public class UserTokens
    {
        public string Token { get; set; }

        public string UserName { get; set; }

        public TimeSpan Validaty { get; set; }

        public string RefreshToken { get; set; }

        public Guid Id { get; set; }

        public string EmailId { get; set; }

        public Guid GuidId { get; set; }

        public DateTime ExpiredTime { get; set; }

    }

After that, we need to add some settings to the app settings so that we can change the global settings for the token generation from appsettings.json without changing any LOCs (Lines of Code).

Note: Please remember to modify the local URL for the valid audience and issuer.

appsettings.json

  "JsonWebTokenKeys": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "64A63153-11C1-4919-9133-EFAF99A9B456",
    "ValidateIssuer": true,
    "ValidIssuer": "https://localhost:44386",
    "ValidateAudience": true,
    "ValidAudience": "https://localhost:44386",
    "RequireExpirationTime": true,
    "ValidateLifetime": true
  }

The next step is to add the JWT Helper class that is used to create a Token and Refresh the Token and validate of Token.

To add a class first create a “JwtHelpers” folder in the root project then create a class "JwtHelper".

Add the code given below,

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using RedisCache.Models;
using System.Collections.Generic;
using System;
using Microsoft.IdentityModel.Protocols;
using System.Linq;
using System.Text;

namespace RedisCache.JwtHelpers
{
    public static class JwtHelper
    {
        public static IEnumerable<Claim> GetClaims(this UserTokens userAccounts, Guid Id)
        {
            IEnumerable<Claim> claims = new Claim[] {
                new Claim("Id", userAccounts.Id.ToString()),
                    new Claim(ClaimTypes.Name, userAccounts.UserName),
                    new Claim(ClaimTypes.Email, userAccounts.EmailId),
                    new Claim(ClaimTypes.NameIdentifier, Id.ToString()),
                    new Claim(ClaimTypes.Expiration, DateTime.UtcNow.AddDays(1).ToString("MMM ddd dd yyyy HH:mm:ss tt"))
            };
            return claims;
        }
        public static IEnumerable<Claim> GetClaims(this UserTokens userAccounts, out Guid Id)
        {
            Id = Guid.NewGuid();
            return GetClaims(userAccounts, Id);
        }
        public static UserTokens GenTokenkey(UserTokens model, JwtSettings jwtSettings)
        {
            try
            {
                var UserToken = new UserTokens();
                if (model == null) throw new ArgumentException(nameof(model));
                // Get secret key
                var key = System.Text.Encoding.ASCII.GetBytes(jwtSettings.IssuerSigningKey);
                Guid Id = Guid.Empty;
                DateTime expireTime = DateTime.UtcNow.AddDays(1);
                UserToken.Validaty = expireTime.TimeOfDay;
                var JWToken = new JwtSecurityToken(issuer: jwtSettings.ValidIssuer, audience: jwtSettings.ValidAudience, claims: GetClaims(model, out Id), notBefore: new DateTimeOffset(DateTime.Now).DateTime, expires: new DateTimeOffset(expireTime).DateTime, signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256));
                UserToken.Token = new JwtSecurityTokenHandler().WriteToken(JWToken);
                UserToken.UserName = model.UserName;
                UserToken.Id = model.Id;
                UserToken.GuidId = Id;
                return UserToken;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static string ValidateToken(string token , JwtSettings jwtSettings)
        {
            if (token == null)
                return null;

            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(jwtSettings.IssuerSigningKey);
            try
            {
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
                    ClockSkew = TimeSpan.Zero
                }, out SecurityToken validatedToken);

                var jwtToken = (JwtSecurityToken)validatedToken;
                var email =  jwtToken.Claims.Single(x => x.Type == ClaimTypes.Email).Value;
                var userName = jwtToken.Claims.Single(Name => Name.Type == ClaimTypes.Name).Value;

                // return user id from JWT token if validation successful
                return email;
            }
            catch
            {
                // return null if validation fails
                return null;
            }
        }
    }
}

So, to inject services let's create a New Class named “AddJWTTokenServicesExtensions” to the separation of concern without messing off the Startup.cs first create a folder named “Extensions” in your root project. Then create the class AddJWTTokenServicesExtensions.

 public static class AddJWTTokenServicesExtensions
    {
        public static void AddJWTTokenServices(IServiceCollection Services, IConfiguration Configuration)
        {
            // Add Jwt Setings
            var bindJwtSettings = new JwtSettings();
            Configuration.Bind("JsonWebTokenKeys", bindJwtSettings);
            Services.AddSingleton(bindJwtSettings);
            Services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = bindJwtSettings.ValidateIssuerSigningKey,
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(bindJwtSettings.IssuerSigningKey)),
                    ValidateIssuer = bindJwtSettings.ValidateIssuer,
                    ValidIssuer = bindJwtSettings.ValidIssuer,
                    ValidateAudience = bindJwtSettings.ValidateAudience,
                    ValidAudience = bindJwtSettings.ValidAudience,
                    RequireExpirationTime = bindJwtSettings.RequireExpirationTime,
                    ValidateLifetime = bindJwtSettings.RequireExpirationTime,
                    ClockSkew = TimeSpan.FromDays(7),
                };
            });
        }
    }

Add using in the first line of the Startup.cs

using RedisCache.Extensions;

inject class in configureservices

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddControllersWithViews();

            services.AddDbContext<DbEmployeeContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration["RedisCacheServerUrl"];
            });

            AddJWTTokenServicesExtensions.AddJWTTokenServices(services, Configuration);
        }

Let's move to the next step which is controller implementations.

Add new WebAPI Controller Named “AccountController”

Here we don’t use any database, we just static values to validate a user and generate Access Token and Authenticate and Authorized Web API Controller

Create add new class Users in models folders

With the following code.

   public class Users
    {
        public string UserName { get; set; }

        public Guid Id { get; set; }

        public string EmailId { get; set; }

        public string Password { get; set; }

    }

Create new class UserLogins in models folders with the following code.

 public class UserLogins
    {
        [Required]
        public string UserName { get; set; }

        [Required]
        public string Password { get; set; }

        public UserLogins() { }
    }

Add new Controller -> API In templates and Rights side Select API Controller -> Empty.

    [Route("api/[controller]/[action]")]
    [ApiController]
    public class AccountController : ControllerBase
    {
        private readonly JwtSettings jwtSettings;

        private readonly DbEmployeeContext _context;

        public AccountController(JwtSettings jwtSettings, DbEmployeeContext context)
        {
            this.jwtSettings = jwtSettings;
            _context = context;
        }

        private IEnumerable<Users> logins = new List<Users>() {
            new Users() {
                    Id = Guid.NewGuid(),
                        EmailId = "admin@gmail.com",
                        UserName = "Admin",
                        Password = "Admin",
                }
        };
        [HttpPost]
        public IActionResult GetToken(UserLogins userLogins)
        {
            try
            {
                var Token = new UserTokens();
                var Valid = logins.Any(x => x.UserName.Equals(userLogins.UserName, StringComparison.OrdinalIgnoreCase));
                if (Valid)
                {
                    var user = logins.FirstOrDefault(x => x.UserName.Equals(userLogins.UserName, StringComparison.OrdinalIgnoreCase));
                    Token = JwtHelper.GenTokenkey(new UserTokens()
                    {
                        EmailId = user.EmailId,
                        GuidId = Guid.NewGuid(),
                        UserName = user.UserName,
                        Id = user.Id,
                    }, jwtSettings);
                }
                else
                {
                    return BadRequest("wrong password");
                }
                return Ok(Token);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        /// <summary>
        /// Get List of UserAccounts
        /// </summary>
        /// <returns>List Of UserAccounts</returns>
        [HttpGet]
        [Authorize(AuthenticationSchemes = Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)]
        public async Task<IActionResult> GetList()
        {
            var products = await _context.Products.ToListAsync();
            string authHeader = this.HttpContext.Request.Headers["Authorization"];
            authHeader = authHeader.Substring("Bearer ".Length).Trim();
            var email = JwtHelper.ValidateToken(authHeader, jwtSettings);
            return Ok(products);
        }
    }

In the above Account, the controller created a List of Login Details that are valid users. You can use database records to validate user logins. Next, we created a method to validate login credentials and generate tokens with the help of JWT Hepler. 

For testing the API we use postman,

https://localhost:44386/api/Account/GetToken

Here you get the token string 

https://localhost:44386/api/Account/GetList
Without passing the token result will be shown below it will give a 401 error.


To Validate or pass the token in the header click on the Authorization tab change the type to bearer token paste generated token in the textbox and then click on send button 

In conclusion,

I described the procedure for generating a JWT access token in this article. Additionally, we were shown how to authorize the WEB API endpoint.

  • |
  • JWT Token Authentication And Authorizations In Web API , JWT Token

Comments

Follow Us On Social Media - Like Us On Facebook

Best Sellers

product 1

Hand Hug Bracelet For Women Men Cuff Bangle Adjustable Lover Couple Bracelets

Can be given as a gift to your family, relatives, or friends

Buy $15.99
product 1

Teddy bear hug bear plush toy bear cub

Can be given as a gift to your family, relatives, or friends


Buy $49.99

Tags

LinkedinLogin
LinkedinProfile
GetLinkedinProfile
C#
Aspnet
MVC
Linkedin
ITextSharp
Export to Pdf
AspNet Core
AspNet
View to Pdf in Aspnet
Model Validation In ASPNET Core MVC 60
Model Validation
Model Validation In ASPNET Core MVC
Model Validation In ASPNET
Image Compression in AspNet
Compress Image in c#
AspNet MVC
Thank you for Downloading....!

Subscribe for more tutorials

Support our team

Continue with Downloading

Welcome To Code2night, A common place for sharing your programming knowledge,Blogs and Videos

  • Panipat
  • info@Code2night.com

Links

  • Home
  • Blogs
  • Tutorial
  • Post Blog

Popular Tags

Copyright © 2023 by Code2night. All Rights Reserved

  • Home
  • Blog
  • Login
  • SignUp
  • Contact
  • Terms & Conditions
  • Refund Policy
  • About Us
  • Privacy Policy
  • Json Beautifier