Designing Perfect REST APIs with ASP.NET Core
RESTful API tasarımında en iyi pratikleri öğrenin. Routing, versioning, error handling ve authentication konularını detaylı olarak inceleyin.
03.e41fe91b numaralı fikir
ASP.NET Core'da JWT Authentication kullanırken en çok karşılaşılan ancak çoğu zaman gözden kaçan iki ayar olan ValidateLifetime ve ClockSkew'i inceliyoruz. JWT'nin yaşam döngüsünü, exp claim'inin nasıl çalıştığını ve Authentication Middleware'in istek Controller'a ulaşmadan önce token doğrulamasını nasıl gerçekleştirdiğini adım adım anlatıyoruz.
Selamlar,
ASP.NET Core'da JWT Authentication kullanan birçok proje görüyoruz ve bu artık oldukça alışık olduğumuz bir yapı. Ancak JWT'nin nasıl çalıştığı ve özellikle bazı ayarların ne işe yaradığı konusunda zaman zaman kafa karışıklığı yaşandığını görüyorum.
Bugün özellikle ValidateLifetime ve ClockSkew ayarlarını konuşacağız.
JWT (JSON Web Token), kullanıcı kimliğini ve sistem tarafından belirlenen bazı bilgileri güvenli şekilde taşımak için kullanılan, dijital olarak imzalanmış bir token standardıdır.
En yaygın kullanım amacı, kullanıcının belirli bir süre boyunca tekrar tekrar giriş yapmadan kimliğini doğrulayabilmesini sağlamaktır.
ASP.NET Core projelerinde genellikle aşağıdaki gibi bir yapı görürüz.
services.AddAuthentication()
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
Burada karşımıza iki önemli ayar çıkıyor:
ValidateLifetimeClockSkewPeki bunlar tam olarak ne yapıyor?
İsmi aslında güzel bir ipucu veriyor.
ValidateLifetime, token'ın geçerlilik süresinin kontrol edilip edilmeyeceğini belirler.
Eğer;
ValidateLifetime = false;
ise token süresi dikkate alınmaz.
Yani token'ın süresi dolmuş olsa bile doğrulama aşamasında bu kontrol yapılmaz.
Fakat;
ValidateLifetime = true;
ise JWT içerisinde mutlaka bir son kullanma tarihi bulunmalı ve bu tarihin geçerli olması gerekir.
JWT oluştururken genellikle şöyle bir tanım yapıyoruz.
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
Buradaki
expires: DateTime.UtcNow.AddHours(1)
ifadesi token'ın 1 saat boyunca geçerli olacağını belirtir.
JWT oluşturulurken bu bilgi payload içerisine exp claim'i olarak eklenir.
Örneğin payload şu şekilde olabilir.
{
"sub": "123",
"name": "Burak",
"exp": 1751880000
}
Buradaki exp değeri Unix Timestamp formatında token'ın son geçerlilik zamanını temsil eder.
ClockSkew saat toleransıdır.
Örneğin;
ClockSkew = TimeSpan.Zero;
dersek;
Süre bittiyse gerçekten bitmiştir.
Hiç tolerans uygulanmaz.
Fakat;
ClockSkew = TimeSpan.FromMinutes(2);
şeklinde ayarlarsak sistem, token süresi dolmuş görünse bile 2 dakika daha kabul eder.
Peki neden böyle bir şeye ihtiyaç duyulur?
Çünkü gerçek sistemlerde;
Bu gibi durumlarda küçük bir tolerans uygulamak istenebilir.
Kullanıcı giriş yaptıktan sonra örneğin şu şekilde bir token ürettik.
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
Artık istemci her istekte bunu gönderir.
Authorization: Bearer eyJhbGciOi...
İstek sunucuya ulaştığında controller henüz çalışmadan önce devreye JWT Authentication Middleware girer.
Yani doğrulama işlemleri aslında Authentication Pipeline içerisinde yapılır.
JWT Authentication Middleware sırasıyla aşağıdaki kontrolleri gerçekleştirir.
Bu kontrollerin tamamı TokenValidationParameters üzerinden yönetilir.
Token'ın süre kontrolü Controller içerisinde yapılmaz.
Yani aşağıdaki gibi kontroller yazmaya gerek yoktur.
if(token.ExpireDate < DateTime.UtcNow)
{
...
}
Çünkü bu kontrol daha istek Controller'a ulaşmadan önce gerçekleştirilir.
Token geçersizse Authentication Middleware isteği durdurur ve Controller hiç çalışmaz.
Doğru yapılandırılmış bir Authentication Pipeline sayesinde;
Küçük gibi görünen bu mekanizma aslında ASP.NET Core güvenlik altyapısının en kritik parçalarından biridir.
Keyifli kodlamalar. 🖖