Merhaba,
JWT (JSON Web Token), modern web uygulamalarında kullanıcı doğrulama (authentication) ve yetkilendirme (authorization) için sıkça kullanılan bir yöntemdir. .NET Core ile JWT kullanarak API’nizi güvenli hale getirebilir ve kullanıcıların erişimlerini kontrol edebilirsiniz.
Bu yazıda, basit bir ASP.NET Core Web API projesinde JWT kullanımını adım adım göstereceğim.
JWT Nedir?
JWT (JSON Web Token), iki taraf arasında bilgi taşımak için kullanılan standart bir JSON tabanlı token yapısıdır. Bu token, kullanıcı bilgilerini ve yetkilerini güvenli bir şekilde taşır; server tarafında session tutmaya gerek kalmadan doğrulama yapılmasını sağlar.
Bir JWT üç ana bölümden oluşur:
1. Header (Başlık)
Token türünü ve kullanılan imzalama algoritmasını belirtir.
Örnek:
{ "alg": "HS256", "typ": "JWT" }
Payload (Yük)
Token içine eklenen bilgiler (claims). Örneğin kullanıcı adı, rol veya token ID gibi bilgiler burada yer alır.
Örnek:
{ "sub": "sinan", "role": "Admin", "exp": 1683600000 }
Signature (İmza)
Header ve Payload’ın gizli anahtar kullanılarak imzalanmış halidir. Bu sayede token’ın değiştirilip değiştirilmediği doğrulanabilir.
JWT genellikle base64url formatında kodlanır ve server ile client arasında taşınır. Örnek bir token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmOWM0MzI5ZC0xMzUwLTRhYjctYTI0NC0yY2YzMDQzNGMyMjAiLCJuYW1lIjoic2luYW4iLCJmdWxsbmFtZSI6IlNpbmFuIFRvc3VuIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiQWRtaW4iLCJuYmYiOjE3Njc2OTcwMTQsImV4cCI6MTc2NzcwMDYxNCwiaXNzIjoiSnd0RGVtb0FQSSIsImF1ZCI6Ikp3dERlbW9DbGllbnQifQ.lFr7bruss5NT_cQxULm59uqk0Ad434UApGPiNaIpbCc
Proje Oluşturma
Öncelikle bir ASP.NET Core Web API projesi oluşturalım. Ben projenin adı olarak JwtDemo ve .NET sürümü olarak da .NET 10’u kullanacağım.
Paketlerin Kurulması
JWT işlemleri için Microsoft’un sağladığı paketleri kullanacağız
Microsoft.AspNetCore.Authentication.JwtBearer
Microsoft.AspNetCore.Authentication.JwtBearer: JWT ile API’yi doğrulamak için gereklidir
AppSettings.json’a JWT Ayarlarını Ekleyelim
JWT için bir gizli anahtar ve token ayarlarını appsettings.json dosyasına ekleyelim:
{
"JwtTokenOptions": {
"SecretKey": "BuCokGizliVeUzunBirAnahtardir123!",
"Issuer": "JwtDemoAPI",
"Audience": "JwtDemoClient",
"ExpiryInMinutes": 60
}
}
-
SecretKey: Token’ı imzalamak için kullanılır, çok gizli tutulmalıdır.
-
Issuer: Token’ı veren sunucu.
-
Audience: Token’ı kullanacak client.
-
ExpiryInMinutes: Token geçerlilik süresi (dakika cinsinden).
JWT Servisini Oluşturma
JWT üretmek için bir interface ve bir service class oluşturacağız. Bu, kodunuzu daha modüler ve test edilebilir hâle getirir. Projenizde Services klasörü altında iki dosya oluşturalım:
-
IJwtService.cs
-
JwtService.cs
IJwtSerice.cs
public interface IJwtService
{
string GenerateJWTToken(string userName,List<string> roles);
}
JwtService.cs
public class JwtService(IOptions<JwtTokenOptions> _tokenOptions) : IJwtService
{
private readonly JwtTokenOptions _tokenOptions = _tokenOptions.Value;
public string GenerateJWTToken(string userName, List<string> roles)
{
// 1. Gizli anahtarı oluşturma
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenOptions.SecretKey));
// 2. Token içinde yer alacak claims (bilgiler)
List<Claim> claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, Guid.NewGuid().ToString()), // Token ID
new Claim(JwtRegisteredClaimNames.Name, userName), // Kullanıcı adı
new Claim("fullname", "Sinan Tosun") // Örnek özel claim
};
// 3. Kullanıcının rollerini claim olarak ekleme
foreach (var item in roles)
{
claims.Add(new Claim(ClaimTypes.Role, item));
}
// 4. JWT token nesnesini oluşturma
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken
(
issuer: _tokenOptions.Issuer, // Token’ı veren
audience: _tokenOptions.Audience, // Token’ı kullanacak client
claims: claims, // Claim listesi
notBefore: DateTime.UtcNow, // Token’ın geçerli olmaya başladığı zaman
expires: DateTime.UtcNow.AddMinutes(_tokenOptions.ExpiryInMinutes), // Token geçerlilik süresi
signingCredentials: new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256) // İmzalama
);
// 5. Token’ı string olarak döndürme
return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
}
}
SymmetricSecurityKey: Token’ın imzalanması için kullanılır ve Gizli anahtar çok önemlidir, kimseyle paylaşılmamalıdır.
Claims: Token içine eklenen bilgiler. Örnek: kullanıcı adı, roller, özel bilgiler.
JwtSecurityToken: Token’ın kendisi burada oluşturulur. issuer, audience, expires gibi alanlar güvenlik ve doğrulama için kritik öneme sahiptir.
SigningCredentials: Token’ın değiştirilmediğini doğrulamak için kullanılır. HmacSha256 algoritması yaygın ve güvenli bir seçenektir.
WriteToken: Token nesnesini base64url formatında string hâline çevirir, client’a gönderilecek hâli budur.
JwtTokenOptions Sınıfı
appsettings.json dosyasında tuttuğumuz JWT konfigürasyonlarını Options Pattern ile okumak için bir sınıf oluşturmamız gerekiyor. Bu sayede ayarlara tip güvenli bir şekilde erişebiliriz.
Options klasörü altında JwtTokenOptions.cs dosyasını oluşturalım:
public class JwtTokenOptions
{
public string SecretKey { get; set; } // Token’ı imzalamak için kullanılacak gizli anahtar
public string Issuer { get; set; } // Token’ı veren sunucu bilgisi
public string Audience { get; set; } // Token’ı kullanacak client bilgisi
public int ExpiryInMinutes { get; set; } // Token geçerlilik süresi (dakika cinsinden)
}
Program.cs Ayarları
ASP.NET Core uygulamasında JWT doğrulama için Program.cs dosyasında gerekli servisleri ve middleware’i eklememiz gerekiyor. Aşağıda adım adım açıklamasıyla birlikte örnek yapı bulunuyor:
// 1. JWT servisinin dependency injection ile eklenmesi
builder.Services.AddScoped<IJwtService, JwtService>();
// 2. appsettings.json'dan token ayarlarının okunması
var tokenOptions = builder.Configuration
.GetSection("JwtTokenOptions")
.Get<JwtTokenOptions>();
// 3. Options Pattern ile JwtTokenOptions konfigürasyonunu servise bağlama
builder.Services.Configure<JwtTokenOptions>(
builder.Configuration.GetSection("JwtTokenOptions")
);
// 4. Authentication ve JWT Bearer konfigürasyonu
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, // Issuer doğrulama
ValidateAudience = true, // Audience doğrulama
ValidateLifetime = true, // Token süresi kontrolü
ValidIssuer = tokenOptions.Issuer, // Beklenen Issuer
ValidAudience = tokenOptions.Audience, // Beklenen Audience
IssuerSigningKey = new SymmetricSecurityKey(
System.Text.Encoding.UTF8.GetBytes(tokenOptions.SecretKey)
), // Token imza anahtarı
ClockSkew = TimeSpan.Zero // Zaman sapmasını sıfırla
};
});
app.UseAuthentication();
-
ValidateIssuer / ValidateAudience → Token’ın kaynağı ve hedefi kontrol edilir.
-
ValidateLifetime → Token’ın süresi dolmuş mu kontrol edilir.
-
IssuerSigningKey → Token imzası doğrulanır.
- ClockSkew = TimeSpan.Zero, sunucunun tanıdığı 5 dakikalık varsayılan tolerans süresini sıfırlayarak token'ın süresi dolduğu anda erişimin kesilmesini sağlar.
Middleware Sırası
app.UseAuthentication() → Önce giriş yapılmalı. app.UseAuthorization() → Daha sonra rol ve yetki kontrolleri yapılır Eğer sıralama ters olursa, yetki kontrolleri çalışmaz ve tüm istekler yetkisiz olarak değerlendirilebilir.
Kullanıcı Giriş Endpoint’i
Controllers/AuthController.cs dosyası:
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IJwtService _jwtService;
public AuthController(IJwtService jwtService)
{
_jwtService = jwtService;
}
[HttpPost("login")]
public IActionResult Login(LoginDto request)
{
// Örnek kullanıcı doğrulama
if (request.Username == "sinan" && request.Password == "123456")
{
// Kullanıcının rollerini belirleme
List<string> roles = new List<string> { "Admin" };
// JWT token üretme
var token = _jwtService.GenerateJWTToken(request.Username, roles);
// Token’ı client’a döndürme
return Ok(new { Token = token });
}
// Yanlış kullanıcı bilgisi durumunda 401 Unauthorized
return Unauthorized(new { error = "Kullanıcı adı veya şifre hatalı" });
}
}
public class LoginDto
{
public string Username { get; set; }
public string Password { get; set; }
}
Basit bir kullanıcı kontrolü yapıyoruz. Doğruysa JWT token üretiliyor ve client’a dönülüyor. Yanlışsa 401 Unauthorized döndürülüyor.
Yetkilendirilmiş Endpoint
JWT doğrulaması sonrasında belirli endpoint’lere sadece yetkili kullanıcıların erişmesini sağlamak için [Authorize] attribute’unu kullanırız.
Controllers/ValuesController.cs örneği:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{ // Herkese açık endpoint
[HttpGet("public")]
public IActionResult Public()
{
return Ok("Bu endpoint herkese açık.");
}
// Sadece doğrulanmış kullanıcıların erişebileceği endpoint
[HttpGet("private")]
[Authorize]
public IActionResult Private()
{
return Ok("Bu endpoint sadece token ile erişilebilir.");
}
}
[Authorize] attribute’u, endpoint’in sadece doğrulanmış kullanıcılar tarafından erişilebileceğini belirtir.
Postman Test Adımları
Token Alma
Localde çalıştığımız port üzerinden (POST) /api/auth/login isteğini
Json
{
"UserName":"sinan",
"Password":"123456"
}
Kullanıcı adı ve şifreyi gönderin Başarılı girişte JWT token bize geri dönecektir..
Yetkilendirilmiş Endpoint’e Erişim
Aynı şekilde localde çalıştığımız port üzerinden (GET) /api/values/private isteğini atacağız.
auth/login endpointden geriye dönen jwt tokeni kopyalayalım. İsteğimizi atacağımız sayfada Authorization > OAuth2.0 placeholder ile Token yazılı olan inputa kopyaldığımız tokeni yapıştıralım.
Eğer Token geçerliyse içerik döner, token geçersiz veya yoksa 401 Unauthorized alırsınız. Rol bazlı kontrol yapıyorsanız ve o role sahip değilseniz 403 hatası alırsınız.
Sonuç
Bu yazımızda, modern web uygulamalarının vazgeçilmezi olan JWT (JSON Web Token) yapısını ve ASP.NET Core üzerinde nasıl yapılandırılacağını adım adım inceledik.
JWT kullanarak;
-
Sunucu tarafında oturum (session) tutma zorunluluğundan kurtulduk
-
Rol tabanlı yetkilendirme ile API güvenliğini standartlara uygun bir seviyeye taşıdık.
Unutmayın: JWT güçlü bir araç olsa da, SecretKey’in güvenliği ve token sürelerinin (Expiry) doğru ayarlanması kritik öneme sahiptir. Ayrıca daha ileri seviye senaryolarda, kullanıcı deneyimini bozmadan güvenliği artırmak için Refresh Token mekanizmalarını kullanmak gerekebilir.
Diğer Bloglarmıda Görüşmek Üzere 👋