Neden JWT?
Klasik cookie-based auth, monolitik bir uygulamada gayet işini görür. Ama:
- Backend'i mobile app ile paylaşıyorsanız
- Birden fazla servis var ve sessiona bağlı kalmak istemiyorsanız
- SPA frontend kullanıyorsanız
JWT (JSON Web Token) doğru seçim oluyor. Token, sunucuda saklanmaz; client her istekte onu Authorization header'ında gönderir.
Kurulum
NuGet paketleri:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
Program.cs içinde:
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opts =>
{
opts.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = config["Jwt:Issuer"],
ValidAudience = config["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(config["Jwt:Key"]!))
};
});
app.UseAuthentication();
app.UseAuthorization();
Login Endpoint
[HttpPost("login")]
public async Task<IActionResult> Login(LoginDto dto)
{
var user = await _userManager.FindByEmailAsync(dto.Email);
if (user is null) return Unauthorized();
var valid = await _userManager.CheckPasswordAsync(user, dto.Sifre);
if (!valid) return Unauthorized();
var token = GenerateJwt(user);
return Ok(new { token });
}
private string GenerateJwt(AppUser user)
{
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, user.Id),
new(ClaimTypes.Email, user.Email!),
new(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _issuer,
audience: _audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(15),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Refresh Token
JWT ömrü kısa olmalı (15 dakika gibi). Ama kullanıcıyı her 15 dakikada yeniden giriş yapmaya zorlayamayız. Çözüm: refresh token.
- Access token — 15 dakika, her istekte gönderilir
- Refresh token — 7-30 gün, sadece "yeni access token al" isteğinde gönderilir, DB'de saklanır
Access süresi dolduğunda, client refresh ile yenisini ister; refresh de DB'de revoke edilebilir.
Güvenlik Notları
- Refresh token'ı
HttpOnly + Securecookie'de saklayın (localStorage yerine) - Access token ömrü 15 dk'yı geçmesin
- JWT key en az 32 karakter ve rastgele üretilmiş olmalı;
appsettings.jsoniçine değil, ortam değişkenine veya Azure Key Vault'a koyun
JWT güvenli; ancak yanlış kullanılırsa kabusa dönüşebilir. Yukarıdaki kuralları takip edin, gerisi standart.