How to Implement JWT Authentication in Asp.Net Core Web API

In this article, we learn a step-by-step process of how to Implement JWT Authentication in Asp.Net Core Web API c# With Database.

What is JWT?

Stands for JSON Web Token is a compact and self-contained method for securely transmitting information between parties as a JSON object.

JWT is used for authentication and authorization purposes and is typically sent in HTTP Headers. It can be implemented in any web application with any backend stack i.e. Asp.Net Core, Java, Python, etc.

It is often used to transmit information that can be verified and trusted, such as user identity and other claims, between an authorization server and a client application.

They are digitally signed and can be encrypted, allowing for the secure transfer of information between parties

Prerequisites

  • Download and install .Net Core 6.0 SDK from here
  • Download and Install Microsoft Visual Studio 2022 from here

Create Asp.Net Core Web API Project

First, we need to create the Asp.net Core Web API project.

  • Open Visual Studio and click the Create New Project Option
  • Select the Template ASP.NET Core Web API

Enter the name of the Project

Select framework and Click on Create

Install NuGet Package

We need to install NuGet Packages

  • Microsoft.AspNet Core.Authentication.JwtBearer
  • System.IdentityModel.Tokens.Jwt.
  • Microsoft Entity Framework Core Sql Server.
  • Microsoft Entity Framework Core Tools

Configure appsetting.json (Asp.Net Core JWT )

Now after the NuGet packages are installed, we need to modify our appsetting.json file and add the secret key and other values and the database connection string.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "connection": "Server=(local)\\MSSQL;Database=Inventory;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "AllowedHosts": "*",
  "JWTToken": {
    "Key": "This is Secret key",
    "Issuer": "https://labpys.com",
    "Audience" : "labpys.com"
  }
}

Also, check the previous article CRUD Operation

Configure Program.cs (Asp.Net Core)

Here we need to configure and register dependencies services and set the ordering of the request pipeline We also, need to add UseAuthentication() and UseAuthorization() middleware and configure addAuthentication with addJwtBearer.

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Text.Json.Serialization;
using Web_API_Tutorials.Helpers;
using Web_API_Tutorials.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddAuthentication(k =>
{
    k.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    k.DefaultChallengeScheme= JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(p =>
{
    var key = Encoding.UTF8.GetBytes(builder.Configuration["JWTToken:key"]);
    p.SaveToken = true;
    p.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience =false,
        ValidateLifetime = false,
        ValidateIssuerSigningKey= true,
        ValidIssuer = builder.Configuration["JWKToekn:key"],
        ValidAudience = builder.Configuration["JWKToekn:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});


builder.Services.AddDbContext<DbContextData>(con => con.UseSqlServer(builder.Configuration.GetConnectionString("connection")));
builder.Services.AddScoped<IUsers, UserServices>();
builder.Services.AddScoped<IJWTTokenServices, JWTServiceManage>();

var app = builder.Build();
app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

Create Models

We need to create a new folder named Entities and add two classes i.e Users, and JWTTokens.

Users.cs

using System.ComponentModel.DataAnnotations;

namespace Web_API_Tutorials.Entities
{
    public class Users
    {
        [Key]
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string UserName { get; set; } 
        public string Password { get; set; }     
    }
}

JWTTokens.cs.

namespace Web_API_Tutorials.Entities
{
    public class JWTTokens
    {
        public string Token { get; set; }
        public string refToken { get; set; }
    }
}

Helpers

We need to create a new folder named Helpers and add a class i.e DbContextData.

DbContextData.cs

using Microsoft.EntityFrameworkCore;
using Web_API_Tutorials.Entities;

namespace Web_API_Tutorials.Helpers
{
    public class DbContextData : DbContext 
    {
        public DbContextData(DbContextOptions<DbContextData> option):base(option)
        {

        }
   
        public virtual DbSet<Users> Users { get; set; }

    }
}

Create Interface and Concrete Class

Now create a new folder named services, then create the interface as IJWTTokenServices, IUsers, and concrete Class JWTServiceManage and UserServices.

IJWTTokenServices.cs

using Web_API_Tutorials.Entities;
 
namespace Web_API_Tutorials.Services
{
    public interface IJWTTokenServices
    {
        JWTTokens Authenticate(Users users);
    }
}

IUsers.cs

using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Models;

namespace Web_API_Tutorials.Services
{
    public interface IUsers
    {
        IEnumerable<Users> GetAll();
    }
}

UserServices.cs

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Helpers;
using Web_API_Tutorials.Models;

namespace Web_API_Tutorials.Services
{
    public class UserServices : IUsers
    {
        private DbContextData _dbcontext;
    
        public UserServices(DbContextData dbContextData) 
        {
            _dbcontext = dbContextData;
        }  
        public IEnumerable<Users> GetAll()
        {
            return _dbcontext.Users;
        }
  
    }
}

JWTServiceManage.cs

After creating a concrete class we need to inherit the interface.

using AutoMapper.Internal;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Helpers;

namespace Web_API_Tutorials.Services
{
    public class JWTServiceManage : IJWTTokenServices
    {
        private readonly IConfiguration _configuration;
        private readonly DbContextData _dbcontext;

        public JWTServiceManage(IConfiguration configuration, DbContextData dbContext)
        {
            _configuration = configuration;
            _dbcontext = dbContext;
        }
        public JWTTokens Authenticate(Users users)
        {
            
            if (!_dbcontext.Users.Any(e => e.UserName == users.UserName && e.Password == users.Password))
            {
                return null;            
            }

            var tokenhandler = new JwtSecurityTokenHandler();
            var tkey = Encoding.UTF8.GetBytes(_configuration["JWTToken:key"]);
            var ToeknDescp = new SecurityTokenDescriptor
            {
                Subject = new System.Security.Claims.ClaimsIdentity(new Claim[]
                {
                    new Claim(ClaimTypes.Name, users.UserName)
                }),
                Expires = DateTime.UtcNow.AddMinutes(5),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tkey), SecurityAlgorithms.HmacSha256Signature)
            };
            var toekn = tokenhandler.CreateToken(ToeknDescp);

            return new JWTTokens { Token = tokenhandler.WriteToken(toekn) };

        }
    }
}

Here we check if the user is valid or not. if the user is not valid, then we return null else we generate JSON Web Token and return the Tokens class object Authorizations are based on the claims contained in the JWT token and set the JWT token expiration time

Migration

Add-Migration 'Initial-Create'
Update-Database

Create Controller

Create UsersController and in its constructor, we inject IJWTTokenServices and IUsers interface. Userscontroller has two Action methods one for authenticating the user and getting a response JSON Web Token(JWT).  The second method Get displays the list of users only if the user is authenticated by using JWT.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Models;
using Web_API_Tutorials.Services;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Web_API_Tutorials.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly IUsers _users;
        private readonly IJWTTokenServices _jwttokenservice;

        // GET: api/<UsersController>

        public UsersController(IUsers users,IJWTTokenServices jWTTokenServices)
        {
            _users = users;
            _jwttokenservice = jWTTokenServices;
        }

        [HttpGet]
        public IActionResult Get()
        {
            
            return Ok(_users.GetAll());
        }

        [AllowAnonymous]
        [HttpPost]
        [Route("Authenticate")]
        public IActionResult Authenticate(Users users)
        {
            var token = _jwttokenservice.Authenticate(users);   

            if (token == null)
            {
                return Ok(new { Message = "Unauthorized" });
            }

            return Ok(token);
        }
 }
}
5 1 vote
Article Rating
Subscribe
Notify of
guest

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jayasimha
Jayasimha
1 year ago

Nice article and great explanation, getting below error when executed
‘DbContextData’ does not contain a definition for ‘Users’, please let me know am i missing any thing.
currently working on .Net 7

I m a developer
I m a developer
1 year ago
Reply to  Jayasimha

Yes, really it’s nice article

Christian Graus
Christian Graus
1 year ago

This, like every other sample I can find, does not work. It throws an error when starting. Why does no one have a code sample to download?

Christian Graus
Christian Graus
1 year ago

Also no method is provided to create users….