Generate Token in .NetCore


Here is a step-by-step guide on how to create a .NET Core Web API project and implement JWT (JSON Web Token) from scratch in .NetCore version 8.

Step 1: Create a .NET Core Web API Project

  1. Open Visual Studio or use the command line.
  2. Create a new project:
    • Select ASP.NET Core Web Application.
    • Click Next, and give your project a name (e.g., GenerateToken).
    • Select API as the project template.
    • Choose your preferred .NET Core version (e.g .NET 8).
    • Click Create.

Project folder structure looks like below image.

Generate Token in .NetCore

Step 2: Install Required NuGet Packages

Add the necessary packages for Identity and Entity Framework:

  1. Right-click on the project in Solution Explorer and select Manage NuGet Packages.

    Generate Token in .NetCore
  2. Search and install the following packages
Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

Right-click on solution and add Data folder (create one if it doesn’t exist) and add a new class named ApplicationDbContext.cs

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;

namespace GenerateToken.Data
{
    public class ApplicationDbContext : IdentityDbContext<IdentityUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
}      

Step 3: Configure the Application in Program.cs

Open the Program.cs file and add the following configurations and add the UseAuthentication() and UseAuthorization() methods.

using JswPoc;
using JswPoc.BLL.Middlewares;
using JswPoc.BLL.ServiceExtentions;
using JswPoc.BLL.Services;
using JswPoc.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));

//builder.Services.AddIdentity<IdentityUser, IdentityRole>()
// .AddEntityFrameworkStores<ApplicationDbContext>()
// .AddDefaultTokenProviders();

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

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

builder.Services.AddAuthorization();

builder.Services.AddSwaggerGen();
builder.Services.AddControllersWithViews();

//Custom Services
builder.Services.AddCustomServices();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();

    using var scope = builder.Services.BuildServiceProvider();
    await SeedData.InitializeAsync(scope);
}
else
{
    app.UseExceptionHandler("/Home/Error");
    // 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.UseStaticFiles();

app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1");
});

app.UseRouting();

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

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
//app.MapRazorPages();

app.Run();

Step 4: Set Up Connection String

Open the appsettings.json file and add the connection string to the database.

{
    "ConnectionStrings": {
        "DefaultConnection": "Server=DESKTOP-V6NQ38C\\SQLEXPRESS;Database=JWTTokenTest;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
        }
    },
    "Jwt": {
        "Key": "v3ryS3cur3R@nd0mK3y!f0rHmacSha256geeecvcy4y4y32y234343rgrt434t5t43ffdsffef",
        "Issuer": "https://localhost:5067/",
        "Audience": "https://localhost:5067/"
    },
    "AllowedHosts": "*"
}

Step 5: Create and Apply Migrations

  1. Open the Package Manager Console from Tools > NuGet Package Manager > Package Manager Console.
  2. Run the following commands to create and apply the migration
PM> Add-Migration InitialCreate
PM> Update-Database

Now run the command.

Generate Token in .NetCore

Now Open the SQL Server database and check it will create automatically database and all tables.

Generate Token in .NetCore

Step 6: Create Register, Login, CreateRole, AssignRoleToUser

Open the Controllers folder and add an AccountController.cs. The AccountController class in your code is an ASP.NET Core MVC controller that handles user authentication and role management functionality. Below is a detailed breakdown of its main functions:

1. Dependencies and Constructor

private readonly IConfiguration configuration;
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly RoleManager _roleManager;

public AccountController(IConfiguration configuration, UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, RoleManager<IdentityRole> roleManager)
{
    this.configuration = configuration;
    _userManager = userManager;
    _signInManager = signInManager;
    _roleManager = roleManager;
}
This controller relies on four injected services:
  • IConfiguration: Used to access configuration settings like JWT options (Issuer, Audience, Key) from appsettings.json.
  • UserManager<IdentityUser>: Manages user-related operations like creating users, finding users by email, etc.
  • SignInManager<IdentityUser>: Manages sign-in operations like password sign-in, signing in a user, or signing out.
  • RoleManager<IdentityRole>: Manages role-related operations like creating and assigning roles.

2. User Registration (Register Methods)

[HttpGet]
public IActionResult Register()
{
    return View();
}

[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = model.Email, Email = model.Email };
        var result = await _userManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }
    return View(model);
}
  • Register() (GET): Returns the registration view to display a registration form.
  • Register(RegisterViewModel model) (POST): Handles user registration by:
    • Checking if the model is valid.
    • Creating a new IdentityUser using UserManager.
    • Signing in the user if creation succeeds.
    • Redirecting to the "Home" page on success.
    • Adding error messages to the model state if registration fails.
  • 3. User Login (Login Methods)

    [HttpGet]
    public IActionResult Login() 
    { 
        return View(); 
    }
    
    [HttpPost]
    public async Task Login([FromBody] LoginViewModel model)
    {
        if (ModelState.IsValid)
        {
            var result = await this._signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                var UserName= model.Email;
                var user = await this._userManager.FindByNameAsync(UserName);
                if (user != null)
                {
                    var roles = await this._userManager.GetRolesAsync(user);
    
                    var issuer = this.configuration["Jwt:Issuer"];
                    var audience = this.configuration["Jwt:Audience"];
                    var key = Encoding.ASCII.GetBytes(this.configuration["Jwt:Key"]);
                    var tokenDescriptor = new SecurityTokenDescriptor
                    {
                        Subject = new ClaimsIdentity(new[]
                        {
                            new Claim("Id", Guid.NewGuid().ToString()),
                            new Claim(ClaimTypes.Name, UserName),
                            new Claim(ClaimTypes.Role, roles.FirstOrDefault()!),
                            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                        }),
                        Expires = DateTime.UtcNow.AddMinutes(5),
                        Issuer = issuer,
                        Audience = audience,
                        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
                    };
                    var tokenHandler = new JwtSecurityTokenHandler();
                    var token = tokenHandler.CreateToken(tokenDescriptor);
                    var stringToken = tokenHandler.WriteToken(token);
    
                    return Ok(new { Token = stringToken });
                }
            }
        }
       return Unauthorized("Invalid Credentials.");
    }
  • Login() (GET) - Returns the login view to display a login form.
  • Login(LoginViewModel model) (POST) - Handles user login and JWT token generation:
    • Validates the login form model.
    • Signs in the user using SignInManager with the provided email and password.
    • If the user is found and login succeeds:
      • Generates a JWT token with user claims like Name, Role, etc., and returns it as a JSON response.
    • Returns Unauthorized if the login fails.
  • 5. Role Management (CreateRole and AssignRoleToUser Methods)

    [HttpPost]
    public async Task<IActionResult> CreateRole(string roleName)
    {
        if (!string.IsNullOrWhiteSpace(roleName))
        {
            var roleExists = await _roleManager.RoleExistsAsync(roleName);
            if (!roleExists)
            {
                var role = new IdentityRole { Name = roleName };
                await _roleManager.CreateAsync(role);
                ViewBag.Message = $"Role '{roleName}' created successfully.";
            }
            else
            {
                ViewBag.Message = $"Role '{roleName}' already exists.";
            }
        }
        return View();
    }
    
    [HttpPost]
    public async Task AssignRoleToUser(string email, string roleName)
    {
        if (!string.IsNullOrWhiteSpace(email) && !string.IsNullOrWhiteSpace(roleName))
        {
            var user = await _userManager.FindByEmailAsync(email);
            if (user != null)
            {
                if (await _roleManager.RoleExistsAsync(roleName))
                {
                    if (!await _userManager.IsInRoleAsync(user, roleName))
                    {
                        var result = await _userManager.AddToRoleAsync(user, roleName);
                        if (result.Succeeded)
                        {
                            ViewBag.Message = $"Role '{roleName}' assigned to user '{email}' successfully.";
                        }
                        else
                        {
                            ViewBag.Message = "Error occurred while assigning role to the user.";
                        }
                    }
                    else
                    {
                        ViewBag.Message = $"User '{email}' is already in role '{roleName}'.";
                    }
                }
                else
                {
                    ViewBag.Message = $"Role '{roleName}' does not exist.";
                }
            }
            else
            {
                ViewBag.Message = $"User with email '{email}' not found.";
            }
        }
        else
        {
            ViewBag.Message = "Email and role name cannot be empty.";
        }
        return View();
    }
  • CreateRole(string roleName): Creates a new role using RoleManager if it doesn't already exist.
  • AssignRoleToUser(string email, string roleName): Assigns a specified role to a user by email if the user and role exist and the user is not already in that role.
  • Now add the above code in AccountController.cs

    using GenerateToken.Models;
    using GenerateToken.BLL.Models;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using System.Threading.Tasks;
    using Microsoft.IdentityModel.Tokens;
    using System.IdentityModel.Tokens.Jwt;
    using System.Security.Claims;
    using System.Text;
    
    namespace AuthDemoApp.Controllers
    {
        public class AccountController : Controller
        { 
    
            private readonly IConfiguration configuration;
            private readonly UserManager<IdentityUser> _userManager;
            private readonly SignInManager<IdentityUser> _signInManager;
            private readonly RoleManager<IdentityRole> _roleManager;
    
            public AccountController(IConfiguration configuration, UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, RoleManager<IdentityRole> roleManager)
            {
                this.configuration = configuration;
                _userManager = userManager;
                _signInManager = signInManager;
                _roleManager = roleManager;
    
            }
    
            [HttpGet]
            public IActionResult Register()
            {
               return View();
            }
    
            [HttpPost]
            public async Task<IActionResult> Register(RegisterViewModel model)
            {
                if (ModelState.IsValid)
                {
                    var user = new IdentityUser { UserName = model.Email, Email = model.Email };
                    var result = await _userManager.CreateAsync(user, model.Password);
                    if (result.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, isPersistent: false);
                        return RedirectToAction("Index", "Home");
                    }
                    foreach (var error in result.Errors)
                    {
                        ModelState.AddModelError(string.Empty, error.Description);
                    }
                }
                return View(model);
            }
    
            [HttpGet]
            public IActionResult Login() 
            { 
               return View(); 
            }
    
            [HttpPost]
            public async Task<IActionResult> Login([FromBody] LoginViewModel model)
            {
                if (ModelState.IsValid)
                {
                    var result = await this._signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
                    if (result.Succeeded)
                    {
                        var UserName= model.Email;
                        var user = await this._userManager.FindByNameAsync(UserName);
                        if (user != null)
                        {
                            var roles = await this._userManager.GetRolesAsync(user);
    
                            var issuer = this.configuration["Jwt:Issuer"];
                            var audience = this.configuration["Jwt:Audience"];
                            //var key = Encoding.ASCII.GetBytes(this.configuration["Jwt:Key"]);
                            var key = Encoding.ASCII.GetBytes(this.configuration["Jwt:Key"]);
                            var tokenDescriptor = new SecurityTokenDescriptor
                            {
                                Subject = new ClaimsIdentity(new[]
                                {
                                    new Claim("Id", Guid.NewGuid().ToString()),
                                    new Claim(ClaimTypes.Name, UserName),
                                    new Claim(ClaimTypes.Role, roles.FirstOrDefault()!),
                                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                                }),
                                Expires = DateTime.UtcNow.AddMinutes(5),
                                Issuer = issuer,
                                Audience = audience,
                                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
                            };
                            var tokenHandler = new JwtSecurityTokenHandler();
                            var token = tokenHandler.CreateToken(tokenDescriptor);
                            var jwtToken = tokenHandler.WriteToken(token);
                            var stringToken = tokenHandler.WriteToken(token);
    
                            return Ok(new { Token = stringToken });
                        }
                    }
                    //ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                }
               return  Unauthorized("Invalid Credentials.");
            }
    
            [HttpPost]
            public async Task Logout()
            {
                await _signInManager.SignOutAsync();
                return RedirectToAction("Index", "Home");
            }
    
            // Role management
            [HttpPost]
            public async Task CreateRole(string roleName)
            {
                if (!string.IsNullOrWhiteSpace(roleName))
                {
                    var roleExists = await _roleManager.RoleExistsAsync(roleName);
                    if (!roleExists)
                    {
                        var role = new IdentityRole { Name = roleName };
                        await _roleManager.CreateAsync(role);
                        ViewBag.Message = $"Role '{roleName}' created successfully.";
                    }
                    else
                    {
                        ViewBag.Message = $"Role '{roleName}' already exists.";
                    }
                }
                return View();
            }
            [HttpPost]
            public async Task<IActionResult> AssignRoleToUser(string email, string roleName)
            {
                // Check if both email and roleName are provided
                if (!string.IsNullOrWhiteSpace(email) && !string.IsNullOrWhiteSpace(roleName))
                {
                    // Find the user by email
                    var user = await _userManager.FindByEmailAsync(email);
                    if (user != null)
                    {
                        // Check if the role exists
                        if (await _roleManager.RoleExistsAsync(roleName))
                        {
                            // Check if the user is already in the role
                            if (!await _userManager.IsInRoleAsync(user, roleName))
                            {
                                // Assign the role to the user
                                var result = await _userManager.AddToRoleAsync(user, roleName);
                                if (result.Succeeded)
                                {
                                    ViewBag.Message = $"Role '{roleName}' assigned to user '{email}' successfully.";
                                }
                                else
                                {
                                    ViewBag.Message = "Error occurred while assigning role to the user.";
                                }
                            }
                            else
                            {
                                ViewBag.Message = $"User '{email}' is already in role '{roleName}'.";
                            }
                        }
                        else
                        {
                            ViewBag.Message = $"Role '{roleName}' does not exist.";
                        }
                    }
                    else
                    {
                        ViewBag.Message = $"User with email '{email}' not found.";
                    }
                }
                else
                {
                    ViewBag.Message = "Email and role name cannot be empty.";
                }
    
                return View();
            }
    
        }
    }

    Run the application and test in Postman.

    Generate Token in .NetCore

    Now open SQL Server JWTTokenTest Database and check registred data.

    Generate Token in .NetCore
  • Now test create role in postman

    Generate Token in .NetCore

    Now open SQL Server JWTTokenTest Database and check role in AspNetRoles table.

    Generate Token in .NetCore

    Now test AssignRoleToUser in postman

    Generate Token in .NetCore

    Now open SQL Server JWTTokenTest Database and check assign role in AspNetUserRoles table.

    Generate Token in .NetCore

    Now test login and create Token in postman

    Generate Token in .NetCore

    You can also download full code to understand more better way. Please follow the below link.

    Download Generate Token Sample code


    Prev Next
  • Top Articles

    1. What is JSON
    2. How to convert a javaScript object in JSON object
    3. Some Important JSON Examples
    4. Common JSON Interview Question