JWT o'rnatish — JwtBearer, token yaratish, sozlash
Muammodan boshlaylik
JWT nima ekanini bilamiz (59-dars). Endi amalda kerak:
- Login da token yaratish va qaytarish
- Har bir so'rovda
Authorization: Bearer ...sarlavhasini o'qish, imzo va muddatni tekshirish - Controller da joriy foydalanuvchini olish
Buni qo'lda yozish — xavfli (algoritm, muddat, kalit tekshiruvidagi bitta xato — butun tizim ochiq). ASP.NET Core da tayyor middleware bor.
Hayotiy o'xshatma
Ofis binosi. Qabulxona (login endpoint) shaxsni tekshirib, magnit karta (token) beradi. Har bir eshikdagi o'quvchi (JwtBearer middleware) kartani tekshiradi: haqiqiymi, muddati o'tmaganmi. Eshik ortidagi xodim (controller) kartani o'zi tekshirmaydi — o'quvchi o'tkazgan bo'lsa, kim kirganini kartadan biladi.
1. Paket va sozlamalar
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
// appsettings.json
{
"Jwt": {
"Issuer": "dokon-api",
"Audience": "dokon-app",
"AccessTokenDaqiqa": 15
}
}
Kalit — appsettings.json da emas, maxfiy joyda (82-dars):
dotnet user-secrets set "Jwt:Kalit" "kamida-32-belgili-uzun-tasodifiy-maxfiy-kalit-qiymati"
public class JwtSozlamalari
{
public string Issuer { get; set; } = "";
public string Audience { get; set; } = "";
public string Kalit { get; set; } = "";
public int AccessTokenDaqiqa { get; set; } = 15;
}
2. Middleware ni ro'yxatdan o'tkazish
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var jwt = builder.Configuration.GetSection("Jwt").Get<JwtSozlamalari>()!;
builder.Services.Configure<JwtSozlamalari>(builder.Configuration.GetSection("Jwt"));
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwt.Issuer,
ValidateAudience = true,
ValidAudience = jwt.Audience,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.Kalit)),
ClockSkew = TimeSpan.FromSeconds(30)
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication(); // tartib muhim: avval kim ekanini aniqlash
app.UseAuthorization(); // keyin ruxsatni tekshirish
app.MapControllers();
[!INFO]
ClockSkewsukut bo'yicha 5 daqiqa — tokenexpdan keyin yana 5 daqiqa qabul qilinadi (serverlar soatidagi farq uchun). 15 daqiqalik token amalda 20 daqiqa yashaydi. Kichikroq qiymat qo'ying.
3. Token yaratish
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
public interface ITokenService
{
string AccessTokenYarat(Foydalanuvchi f);
}
public class TokenService(IOptions<JwtSozlamalari> opt) : ITokenService
{
private readonly JwtSozlamalari _s = opt.Value;
public string AccessTokenYarat(Foydalanuvchi f)
{
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Sub, f.Id.ToString()),
new(JwtRegisteredClaimNames.Email, f.Email),
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new(ClaimTypes.Role, f.Rol)
};
var kalit = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_s.Kalit));
var imzo = new SigningCredentials(kalit, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _s.Issuer,
audience: _s.Audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(_s.AccessTokenDaqiqa),
signingCredentials: imzo);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
builder.Services.AddSingleton<ITokenService, TokenService>();
4. Login endpoint
public record LoginDto(string Email, string Parol);
public record TokenJavob(string AccessToken, int AmalQilishSoniya);
[ApiController]
[Route("api/auth")]
public class AuthController(DokonDbContext db, ITokenService tokens, IOptions<JwtSozlamalari> opt) : ControllerBase
{
[HttpPost("login")]
public async Task<ActionResult<TokenJavob>> Login(LoginDto dto, CancellationToken ct)
{
var f = await db.Foydalanuvchilar
.FirstOrDefaultAsync(x => x.Email == dto.Email.ToLowerInvariant(), ct);
if (f is null || !BCrypt.Net.BCrypt.Verify(dto.Parol, f.ParolXesh))
return Unauthorized(new { xato = "Email yoki parol noto'g'ri" });
return new TokenJavob(tokens.AccessTokenYarat(f), opt.Value.AccessTokenDaqiqa * 60);
}
}
POST /api/auth/login
Content-Type: application/json
{ "email": "lola@mail.uz", "parol": "Kuchli!Parol2026" }
{ "accessToken": "eyJhbGciOiJIUzI1NiIs...", "amalQilishSoniya": 900 }
5. Joriy foydalanuvchini olish
[Authorize]
[HttpGet("men")]
public IActionResult Men()
{
var id = User.FindFirstValue(ClaimTypes.NameIdentifier);
var email = User.FindFirstValue(ClaimTypes.Email);
var rol = User.FindFirstValue(ClaimTypes.Role);
return Ok(new { id, email, rol });
}
[!WARNING] JwtBearer sukut bo'yicha
subclaim iniClaimTypes.NameIdentifierga,ClaimTypes.Emailga xaritalaydi (mapping). Shuning uchunUser.FindFirstValue("sub")nullqaytarishi mumkin. Asl nomlarni saqlash uchun:o.MapInboundClaims = false;— keyinUser.FindFirstValue("sub")ishlaydi, lekin rol uchunRoleClaimType = "role"ni ham sozlang.
Qulay kengaytma:
public static class ClaimsKengaytma
{
public static int FoydalanuvchiId(this ClaimsPrincipal u) =>
int.Parse(u.FindFirstValue(ClaimTypes.NameIdentifier)
?? throw new UnauthorizedAccessException());
}
var meningId = User.FoydalanuvchiId();
Mijoz tomonda
curl https://localhost:5001/api/auth/men \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Token yo'q yoki yaroqsiz — 401 Unauthorized; WWW-Authenticate: Bearer error="invalid_token", error_description="The token expired..." sarlavhasida sabab.
[!TIP]
JwtSecurityTokenHandlero'rniga yangi va tezroqJsonWebTokenHandler(Microsoft.IdentityModel.JsonWebTokens) bor — .NET 8+ da JwtBearer ichida sukut bo'yicha ishlatiladi. Token yaratishda hamSecurityTokenDescriptor+JsonWebTokenHandler.CreateTokenishlatish mumkin.
Tez-tez uchraydigan xatolar
UseAuthentication unutilgan yoki UseAuthorization dan keyin — har doim 401.
Kalit 32 baytdan qisqa:
IDX10720: Unable to create KeyedHashAlgorithm for algorithm 'HS256', the key size must be greater than: '256' bits
Issuer/Audience yaratishda va tekshirishda farq qiladi — IDX10214: Audience validation failed.
Kalit kodda yoki git da — kim ko'rsa, istalgan token yasaydi.
Xulosa
AddAuthentication().AddJwtBearer() — TokenValidationParameters: issuer, audience, muddat va imzo kaliti tekshiruvi; ClockSkew ni kamaytiring. Middleware tartibi: UseAuthentication → UseAuthorization.
Token — JwtSecurityToken (claims: sub, email, jti, rol; expires; HmacSha256 imzo) → WriteToken. Login: parolni Verify → token qaytarish. Controller da — User.FindFirstValue(ClaimTypes.NameIdentifier); claim mapping ga e'tibor. Kalit — kamida 32 bayt, maxfiy joyda.
Keyingi dars
61-dars: [Authorize] va [AllowAnonymous] — endpoint himoyasi, policy