TEst

ASP.NET Core full auth setup reference note

ASP.NET Core · EF Core · JWT

Full auth setup — backend reference

ASP.NET Core Identity + JWT Bearer। যেকোনো নতুন প্রজেক্টে এই ফ্লো follow করলেই হবে।

NuGet packages
IdentityDbContext
Migration
Program.cs config
TokenService
Seed data
AuthController
Authorize

1
NuGet packages install

একবারই

প্রজেক্টে শুরুতেই এই দুটো প্যাকেজ ইনস্টল করতে হবে। Identity এবং JWT দুটোই লাগবে।

Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer

NuGet Package Manager বা terminal থেকে dotnet add package <name> দিয়ে করা যাবে।

2
ApplicationDbContext → IdentityDbContext

একবারই

DbContext এর বদলে IdentityDbContext inherit করাতে হবে। এতেই AspNetUsers, AspNetRoles সব টেবিল auto তৈরি হয়।

ApplicationDbContext.cs
public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options)
        : base(options) { }

    // তোমার নিজের টেবিলগুলো এখানে
    public DbSet<BlogPost> BlogPosts { get; set; }
    public DbSet<Category> Categories { get; set; }
}

3
Migration + Database update

terminal

IdentityDbContext যোগ করার পর migration দিতে হবে। এতে Identity এর সব টেবিল DB তে চলে আসবে।

dotnet ef migrations add “Adding Identity”
dotnet ef database update

DB তে AspNetUsers, AspNetRoles, AspNetUserRoles, AspNetUserClaims ইত্যাদি টেবিল তৈরি হবে।

4
Program.cs — Identity + JWT config

গুরুত্বপূর্ণ

তিনটি কাজ করতে হবে এখানে — Identity register, JWT Authentication configure, এবং pipeline এ যোগ করা।

Program.cs — services
// ১. Identity
builder.Services.AddIdentityCore<IdentityUser>(options =>
{
    options.Password.RequireDigit = false;
    options.Password.RequireLowercase = false;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = false;
    options.Password.RequiredLength = 6;
})
.AddRoles<IdentityRole>()
.AddTokenProvider<DataProtectorTokenProvider<IdentityUser>>("Blog")
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

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

// ৩. TokenService register
builder.Services.AddScoped<ITokenService, TokenService>();

Program.cs — pipeline (UseRouting এর পরে)
app.UseAuthentication();
app.UseAuthorization();

appsettings.json
"Jwt": {
  "Key": "A_Very_Secret_Key_That_Is_At_Least_32_Characters_Long",
  "Issuer": "https://localhost:7071",
  "Audience": "https://localhost:7071"
}

Key অবশ্যই ৩২+ character হতে হবে, নাহলে runtime error আসবে।

5
ITokenService + TokenService

গুরুত্বপূর্ণ

এটাই “টোকেন ফ্যাক্টরি”। Claims তৈরি করে, secret key দিয়ে sign করে, string হিসেবে return করে।

ITokenService.cs
public interface ITokenService
{
    string CreateJwtToken(IdentityUser user, List<string> roles);
}

TokenService.cs
public class TokenService : ITokenService
{
    private readonly IConfiguration configuration;

    public TokenService(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public string CreateJwtToken(IdentityUser user, List<string> roles)
    {
        // ১. Claims — টোকেনে কী তথ্য থাকবে
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Email, user.Email)
        };
        foreach (var role in roles)
            claims.Add(new Claim(ClaimTypes.Role, role));

        // ২. Secret key
        var key = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(configuration["Jwt:Key"]));

        // ৩. Signing credentials (algorithm)
        var credentials = new SigningCredentials(
            key, SecurityAlgorithms.HmacSha256);

        // ৪. Token object তৈরি
        var token = new JwtSecurityToken(
            issuer: configuration["Jwt:Issuer"],
            audience: configuration["Jwt:Audience"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(60),
            signingCredentials: credentials);

        // ৫. String হিসেবে return
        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

6
Data Seeding — Admin user + roles

একবারই

OnModelCreating এ seed data দিলে প্রতি database update এ check করে — না থাকলে নিজে তৈরি করে। ম্যানুয়ালি SQL লেখার দরকার নেই।

ApplicationDbContext.cs — OnModelCreating
protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    var adminRoleId   = "a71a55ad-7f0b-4cf9-9291-67a96c21b5a2";
    var readerRoleId  = "c32dc752-b293-41fa-ad1d-f23605833215";
    var adminUserId   = "d6e321e8-3486-4f3d-979b-22d7a26f043e";

    // Roles
    builder.Entity<IdentityRole>().HasData(new List<IdentityRole>
    {
        new IdentityRole { Id = adminRoleId,  Name = "Admin",
            NormalizedName = "ADMIN" },
        new IdentityRole { Id = readerRoleId, Name = "Reader",
            NormalizedName = "READER" }
    });

    // Admin user
    var adminUser = new IdentityUser
    {
        Id = adminUserId,
        UserName = "admin@myblog.com",
        Email = "admin@myblog.com",
        NormalizedEmail = "ADMIN@MYBLOG.COM",
        NormalizedUserName = "ADMIN@MYBLOG.COM"
    };
    adminUser.PasswordHash = new PasswordHasher<IdentityUser>()
        .HashPassword(adminUser, "Admin@123");

    builder.Entity<IdentityUser>().HasData(adminUser);

    // Admin user → Admin role
    builder.Entity<IdentityUserRole<string>>().HasData(
        new IdentityUserRole<string>
        {
            RoleId = adminRoleId,
            UserId = adminUserId
        });
}

dotnet ef migrations add “Seed Roles and Admin User”
dotnet ef database update

7
AuthController — Login + Register

গুরুত্বপূর্ণ

দুটো endpoint — /api/auth/register নতুন reader তৈরি করে, /api/auth/login JWT token return করে।

DTOs
public class LoginRequestDto
{
    [Required][EmailAddress]
    public string Email { get; set; }
    [Required]
    public string Password { get; set; }
}

public class RegisterRequestDto
{
    [Required][EmailAddress]
    public string Email { get; set; }
    [Required][MinLength(6)]
    public string Password { get; set; }
}

AuthController.cs
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly UserManager<IdentityUser> userManager;
    private readonly ITokenService tokenService;

    public AuthController(UserManager<IdentityUser> userManager,
                          ITokenService tokenService)
    {
        this.userManager = userManager;
        this.tokenService = tokenService;
    }

    // POST /api/auth/login
    [HttpPost("login")]
    public async Task<IActionResult> Login(
        [FromBody] LoginRequestDto request)
    {
        var user = await userManager.FindByEmailAsync(request.Email);
        if (user != null)
        {
            var ok = await userManager
                .CheckPasswordAsync(user, request.Password);
            if (ok)
            {
                var roles = await userManager.GetRolesAsync(user);
                var token = tokenService
                    .CreateJwtToken(user, roles.ToList());
                return Ok(new { Email = request.Email,
                                Token = token, Roles = roles });
            }
        }
        return BadRequest("Invalid Email or Password");
    }

    // POST /api/auth/register
    [HttpPost("register")]
    public async Task<IActionResult> Register(
        [FromBody] RegisterRequestDto request)
    {
        var user = new IdentityUser
        {
            UserName = request.Email,
            Email = request.Email
        };
        var result = await userManager
            .CreateAsync(user, request.Password);
        if (result.Succeeded)
        {
            var roleResult = await userManager
                .AddToRoleAsync(user, "Reader");
            if (roleResult.Succeeded)
                return Ok("User registered successfully!");
        }
        return BadRequest(result.Errors);
    }
}

8
Endpoint protect করা — [Authorize]

শেষ ধাপ

Token ছাড়া কেউ sensitive endpoint access করতে পারবে না। Role-based বা শুধু authenticated user দুইভাবেই করা যায়।

যেকোনো Controller বা Action এ
// শুধু logged-in user
[Authorize]

// শুধু Admin role
[Authorize(Roles = "Admin")]

// Admin অথবা Reader
[Authorize(Roles = "Admin,Reader")]

// উদাহরণ — শুধু Admin delete করতে পারবে
[Authorize(Roles = "Admin")]
[HttpDelete("{id:Guid}")]
public async Task<IActionResult> DeleteBlogPost(Guid id)
{
    // লজিক...
}

Swagger থেকে test করতে হলে Authorize button এ গিয়ে Bearer <token> format এ token paste করতে হবে।

Admin login
admin@myblog.com
Admin@123

Token expiry
60 minutes

Default new user role
Reader

Algorithm
HmacSha256

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top