Friday, August 26, 2022

JWT Authentication in ASP.NET Core Web API

 In this tutorial we'll go through a simple example of how to implement 

JWT (JSON Web Token) authentication in an ASP.NET Core 3.0 API with C#.


1. Create a web api application using asp.net core :(JWTAuth)

2. Create a Controller:
LoginController:
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using JWTAuth.Model;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;

namespace JWTAuth.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        private IConfiguration _config;

        public LoginController(IConfiguration config)
        {
            _config = config;
        }

        [HttpGet]
        public IActionResult Login(string userId, string pass)
        {
            UserModel login = new UserModel();
            login.Username = userId;
            login.Pass = pass;
            IActionResult response = Unauthorized();

            var user = AuthenticateUser(login);
            if (user != null)
            {
                var tokenString = GenerateJSONWebToken(user);
                response = Ok(new { token = tokenString });
            }

            return response;
        }
        private UserModel AuthenticateUser(UserModel login)
        {
            UserModel user = null;
            if (login.Username == "ashproghelp" && login.Pass == "123")
            {
                user = new UserModel { Username = "AshProgHelp", EmailAddress = "AshProgHelp@gmail.com", Pass = "123" };
            }
            return user;
        }
        private string GenerateJSONWebToken(UserModel userInfo)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var claims = new[] {
            new Claim(JwtRegisteredClaimNames.Sub, userInfo.Username),
            new Claim(JwtRegisteredClaimNames.Email, userInfo.EmailAddress),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };

            var token = new JwtSecurityToken(
                issuer: _config["Jwt:Issuer"],
                audience: _config["Jwt:Issuer"],
                claims,
                expires: DateTime.Now.AddMinutes(120),
                signingCredentials: credentials);
            var encodetoken = new JwtSecurityTokenHandler().WriteToken(token);
            return encodetoken;
        }

        [Authorize]
        [HttpPost("Post")]
        public string Post()
        {
            var identity = HttpContext.User.Identity as ClaimsIdentity;
            IList<Claim> claim = identity.Claims.ToList();
            var userName = claim[0].Value; //claim.Where(c => c.Type == "Sub").Select(c => c.Value).SingleOrDefault();
            return "Welcome To:" + userName;
        }

        [HttpGet ("GetValue")]
        [Authorize]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2", "value3", "value4", "value5" };
        }
    }
}

3. appsettings.json:

 "Jwt": {
    "Key": "AshProghelpSecretKey",
    "Issuer": "ashproghelp.com"
  }

4. Startup.cs:
      public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().Build());
            });
            services.AddControllers();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = Configuration["Jwt:Issuer"],
                        ValidAudience = Configuration["Jwt:Issuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
                    };
                });

                 services.AddMvc();
        }

--==================================================

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

5. Create UserModel Calss:
 public class UserModel
    {
        public string Username { get; set; }
        public string Pass { get; set; }
        public string EmailAddress { get; set; }
        public DateTime DateOfJoin { get; set; }
    }

Kendo Grid Settings

 var GridSummaryManager = {

    gridDataSource: function () {

        var gridDataSource = new kendo.data.DataSource({

            type: "json",

            serverPaging: true,

            serverSorting: true,

            serverFiltering: true,

            allowUnsort: true,

            pageSize: 10,

            transport: {

                read: {

                    url: '../Unit/GetUnitSummary/',

                    type: "POST",

                    dataType: "json",

                    contentType: "application/json; charset=utf-8"

                },

                parameterMap: function (options) {

                    return JSON.stringify(options);

                }

            },

            schema: {

                data: "Items", total: "TotalCount",

                model: {

                    fields: {

                        ExpDate: {

                            type: "date",

                            template: '#= kendo.toString("dd-MMM-yyyy") #',

                            editable: false

                        }

                    }

                },

            }

        });

        return gridDataSource;

    }

};


var GridSummaryHelper = {

    InitUnitSummary: function () {

       GridSummaryHelper.GenerateGrid();

    },


    GenerateGrid: function () {

        $("#grdSummary").kendoGrid({

            dataSource: GridSummaryManager.gridDataSource(),

            pageable: {

                refresh: true,

                serverPaging: true,

                serverFiltering: true,

                serverSorting: true

            },

            filterable: true,

            sortable: true,

            columns: GridSummaryHelper.GenerateColumns(),

            editable: false,

            navigatable: true,

            selectable: "row"

        });

    },


    GenerateColumns: function () {

        return columns = [

               { field: "UnitId", hidden: true },

               { field: "UnitName", title: "Unit Name", width: 70, editable: false },

               { field: "CompanyName", title: "Company Name", width: 70, editable: false },

               { field: "UnitNameBan", title: "Unit Name (Bangla)", width: 70, editable: false },

               { field: "IsActive", title: "Activity", width: 50, editable: false, template: '#=IsActive==true?"Active":"InActive"#' },

               { field: "Edit", title: "Edit/View", filterable: false, width: 30, template: '<button type="button" class="btn btn-default btn-sm" value="Edit" id="btnEdit" onClick="UnitSummaryHelper.clickEventForEditButton()" ><span class="glyphicon glyphicon-edit"></span></button>', sortable: false }

        ];

    },


    clickEventForEditButton: function () {


        var entityGrid = $("#grdUnitSummary").data("kendoGrid");

        var selectedItem = entityGrid.dataItem(entityGrid.select());


For New Version:

===================================

 e.preventDefault();

        var grid = $("#grdBuyerCostingSummary").data("kendoGrid");

        var tr = $(e.currentTarget).closest("tr");

        var selectedItem = this.dataItem(tr);

        grid.select(tr);

=================================

        if (selectedItem != null) {

            GridDetailsHelper.FillForm(selectedItem);

        }

    },

};


AjaxManager


var AjaxManager = {


    //MVC call

    GetJsonResult: function (serviceUrl, jsonParams, isAsync, isCache, successCallback, errorCallback) {

        $.ajax({

            type: "GET",

            async: isAsync,

            cache: isCache,

            url: serviceUrl,

            data: jsonParams,

            contentType: "application/json; charset=utf-8",

            dataType: "json",

            success: successCallback,

            error: errorCallback

        });

    },

    GetJsonResult2: function (serviceUrl, jsonParams, isAsync, isCache, successCallback, errorCallback) {

        $.ajax({

            type: "GET",

            async: isAsync,

            cache: isCache,

            url: serviceUrl,

            data: "{" + jsonParams + "}",

            contentType: "application/json; charset=utf-8",

            dataType: "json",

            success: successCallback,

            error: errorCallback

        });

    },

    GetJsonResultPOST: function (serviceUrl, jsonParams, isAsync, isCache, successCallback, errorCallback) {

        $.ajax({

            type: "POST",

            async: isAsync,

            cache: isCache,

            url: serviceUrl,

            data: "{" + jsonParams + "}",

            contentType: "application/json; charset=utf-8",

            dataType: "json",

            success: successCallback,

            error: errorCallback

        });

    },

    GetAPI: function (serviceUrl, successCallback, errorCallback) {

        $.ajax({

            type: "GET",

            url: serviceUrl,

            dataType: "json",

            success: successCallback,

            error: errorCallback

        });

    },


    GetJson: function (serviceUrl, jsonParams, successCallback, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            data: jsonParams,

            type: "POST",

            processData: true,

            contentType: "application/json",

            dataType: "json",

            success: successCallback,

            error: errorCallback

        });

    },

    SendJson: function (serviceUrl, jsonParams, successCallback, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            data: jsonParams,

            async: true,

            cache: false,

            type: "POST",

            success: successCallback,

            error: errorCallback

        });

    },

    SendJson2: function (serviceUrl, jsonParams, successCallback, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            async: false,

            type: "POST",

            data: "{" + jsonParams + "}",

            dataType: "json",

            contentType: "application/json; charset=utf-8",

            success: successCallback,

            error: errorCallback

        });

    },

    SendJson3: function (serviceUrl, jsonParams, successCallback, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            async: true,

            type: "POST",

            data: "{" + jsonParams + "}",

            dataType: "json",

            contentType: "application/json; charset=utf-8",

            success: successCallback,

            error: errorCallback

        });

    },

    SendJsonWithToken: function (serviceUrl, jsonParams, successCallback, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            async: false,

            type: "POST",

            data: "{" + jsonParams + "}",

            dataType: "json",

            contentType: "application/json; charset=utf-8",

            beforeSend: function (xhr) {

                //   localStorage.setItem('token', token);need to set token after login

                xhr.setRequestHeader("Authorization", 'Bearer ' + localStorage.getItem('token'));

            },

            success: successCallback,

            error: errorCallback

        });

    },


    GetReport: function (serviceUrl, jsonParams, errorCallback) {

        jQuery.ajax({


            url: serviceUrl,

            async: false,

            type: "POST",

            data: "{" + jsonParams + "}",

            // dataType: "json",

            contentType: "application/json; charset=utf-8",

            success: function () {


                window.open('../Reports/ReportViewer.aspx', '_newtab');

                //window.open("../Reports/ReportViewer.aspx", 'mywindow', 'fullscreen=yes, scrollbars=auto',);

            },


            error: errorCallback


        });


    },

    PrintReport: function (serviceUrl, jsonParams, errorCallback) {

        jQuery.ajax({

            url: serviceUrl,

            async: false,

            type: "POST",

            data: "{" + jsonParams + "}",

            // dataType: "json",

            contentType: "application/json; charset=utf-8",

            error: errorCallback

        });


    },

    GetRdlcReport: function (serviceUrl, jsonParams, errorCallback) {


        jQuery.ajax({


            url: serviceUrl,

            async: false,

            type: "POST",

            data: "{" + jsonParams + "}",

            // dataType: "json",

            contentType: "application/json; charset=utf-8",

            success: function () {


                window.open('../Reports/ReportViewerRDLC.aspx', '_blank');

                //window.open("../Reports/ReportViewer.aspx", 'mywindow', 'fullscreen=yes, scrollbars=auto',);

            },


            error: errorCallback


        });


    },

   

    


   

  

    getDayDifference: function (date1, date2) {


        // The number of milliseconds in one day

        var ONE_DAY = 1000 * 60 * 60 * 24;


        // Convert both dates to milliseconds

        var date1_ms = new Date(date1).getTime();

        var date2_ms = new Date(date2).getTime();


        // Calculate the difference in milliseconds

        var difference_ms = Math.abs(date1_ms - date2_ms);


        // Convert back to days and return

        return Math.round(difference_ms / ONE_DAY);


    },

  

    daysBetween: function (date1, date2) {


        // The number of milliseconds in one day

        var ONE_DAY = 1000 * 60 * 60 * 24;


        // Convert both dates to milliseconds

        var date1_ms = new Date(date1).getTime();

        var date2_ms = new Date(date2).getTime();


        // Calculate the difference in milliseconds

        var difference_ms = Math.abs(date1_ms - date2_ms);


        // Convert back to days and return

        return Math.round(difference_ms / ONE_DAY);


    },


    isFloat: function (s) {

        return /^\s*(\d+)?(\.(\d+))?\s*$/.test(s);

    },

    isDate: function (str) {

        var m = str.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);

        return (m) ? true : false;

    },

  

    isEmpty: function (s) {

        return !((s != null) && /^\s*(\S+(\s+\S+)*)\s*$/.test(s));

    },

    checkSpecialCharacters: function (id) {


        var checkString = $("#" + id).val();


        var regex = /[^\w\s&]/gi;



        if (checkString != "") {

            if (regex.test(checkString)) {

                AjaxManager.MsgBox('warning', 'center', 'Special Characters:', 'Your search string contains illegal characters.',

                      [{

                          addClass: 'btn btn-primary', text: 'Ok', onClick: function ($noty) {

                              $noty.close();

                              return (false);

                          }

                      }]);


            }

            else {

                return true;

            }

        }


    },

    replaceSingleQoute: function (id) {


        var checkString = $("#" + id).val();

        checkString = checkString.replace(/'/g, "''");

        return checkString;


    },



    validator: function (divId) {


        var validator = divId.kendoValidator().data("kendoValidator"),

           status = $(".status");


        if (validator.validate()) {

            status.text("").addClass("valid");

            return true;

        } else {

            status.text("Oops! There is invalid data in the form.").addClass("invalid");

            return false;

        }

    },


    Trim: function (s) {

        //return s.replace(s,"/^ *(\w+ ?)+ *$/", "");

        return (s.replace(/\s+/g, ' ')).trim();

    },

    isValidItem: function (ctrlId, isClear) {


        var cmbBox = $("#" + ctrlId).data("kendoComboBox");


        if (cmbBox.value() != "" && cmbBox.value() == cmbBox.text()) {

            AjaxManager.MsgBox('warning', 'center', 'Invalid Item:', 'No Item matched with your Input data as like "[' + cmbBox.text() + ']"!', [{

                addClass: 'btn btn-primary',

                text: 'Ok',

                onClick: function ($noty) {

                    $noty.close();

                    //cmbBox.focus();

                    if (isClear)

                        cmbBox.value('');



                }

            }

            ]);

            return false;

        } else {

            return true;

        }

    },


};                       //End AjaxManager



=============How to call=======================

   GenerateBranchCombo: function (companyId) {

        var objBranch = "";

        var jsonParam = "companyId=" + companyId;

        var serviceUrl = "../../Branch/GetBranchByCompanyIdForCombo/";

        AjaxManager.GetJsonResult(serviceUrl, jsonParam, false, false, onSuccess, onFailed);


        function onSuccess(jsonData) {

            objBranch = jsonData;

        }

        function onFailed(error) {

            window.alert(error.statusText);

        }

        return objBranch;

    },


===========Kendo Combo Load=====


 GenerateDistrictCombo: function (sectionId, identity) {

        //var objSection = smsCommonManager.GetClassData(sectionId);

        $("#" + identity).kendoComboBox({

            placeholder: "All",

            dataTextField: "DistrictName",

            dataValueField: "DistrictId",

            dataSource: [],

            change: function () {

                AjaxManager.isValidItem(identity, true);

            }

        });

    },

JWT Authentication in ASP.NET Core Web API

  In this tutorial we'll go through a simple example of how to implement  JWT (JSON Web Token) authentication in an ASP.NET Core 3.0 API...