JWT exp/iat/nbf Hataları: Kimlik Doğrulamasını Bozan Zaman Talebi Hataları

JWT zaman talepleri — exp, iat ve nbf — aldatıcı derecede basittir. Onlar sadece Unix zaman damgalarıdır. Yine de üretimde en sinir bozucu kimlik doğrulama hatalarından bazılarına neden oluyorlar: süresi çok kısa sürede dolan jetonlar, bir sunucuda çalışıp diğerinde çalışmayan jetonlar ve süresi hiç dolmayan jetonlar.
Bu makale en yaygın zaman talebi hatalarını, bunların neden oluştuğunu ve bunların güvenli varsayılanlarla nasıl düzeltileceğini kapsar.
Exp, iat ve nbf nasıl çalışır
Her JWT, yükünde zamanla ilgili üç talep taşıyabilir:
- exp (Son Kullanma Süresi) — jetonun bu zaman damgasından sonra kabul edilmemesi ZORUNLUDUR
- iat (Yayınlanma Tarihi) — jetonun oluşturulduğu tarih
- nbf (Önce Değil) — jetonun bu zaman damgasından önce kabul edilmemesi ZORUNLUDUR
Üçü de sayısal tarihlerdir: 1970-01-01T00:00:00Z'den (Unix dönemi) bu yana geçen saniye sayısı. Milisaniye değil, saniye. Bu ayrım tek başına tüm JWT zaman hatalarının kabaca %20'sine neden olur.
Herhangi bir jetondaki zaman taleplerini anında incelemek için JWT Kodlayıcı'mizi kullanın.
Hata #1: Saniye Yerine Milisaniye Kullanımı
JavaScript'in Date.now() milisaniye değerini döndürür. JWT spesifikasyonu saniye gerektirir. exp öğesini Date.now() + 3600000 olarak ayarlamak, süresi bir saat içinde değil 2089 yılında dolacak bir belirteç oluşturur.
// YANLIŞ — milisaniye
const exp = Date.now() + 3600000; // DOĞRU — saniye
const exp = Math.floor(Date.now() / 1000) + 3600;JWT kütüphanelerinin çoğu bunu dahili olarak halleder, ancak yükleri manuel olarak oluşturuyorsanız kontrol etmeniz gereken ilk şey budur.
Hata #2: Exp Talebi Tamamen Eksik
Eğer exp ayarlamayı unutursanız, birçok kütüphane memnuniyetle hiçbir zaman sona ermeyen bir belirteç yaratacaktır. Bu bir güvenlik riskidir: Sızan bir token sonsuza kadar geçerli kalır.
Her zaman exp olarak ayarlayın. Her zaman sunucuda doğrulayın. Kitaplığınız varsayılan olarak exp içermeyen belirteçleri reddetmiyorsa, bunu yapacak şekilde yapılandırın.
// Node.js jsonwebtoken — süre sonunu zorunlu kıl
jwt.verify(token, gizli, { maxAge: '1h' });Hata #3: Sunucular Arasında Saatin Çarpıklığı
Sunucu A, saat 14:00:00'da bir jeton yayınlar. Sunucu B'nin saati 13:59:55 (5 saniye geride) diyor. Belirteçte nbf: 1711540800 (14:00:00) varsa, Sunucu B bunu "henüz geçerli değil" olarak reddeder.
Bu özellikle şu ülkelerde yaygındır:
- Senkronize edilmemiş saatlere sahip mikro hizmet mimarileri
- Kapsayıcıların saat kaymasına sahip olduğu sunucusuz işlevler
- Cihaz saatinin manuel olarak ayarlandığı mobil uygulamalar
Düzeltme
Küçük bir saat toleransına izin verin ("boşluk" olarak da adlandırılır) — genellikle 30-60 saniye:
// jsonwebtoken
jwt.verify(belirteç, sır, { clockTolerance: 30 }); // jose (Node.js)
wait jwtVerify(token, key, { clockTolerance: '30s' });Toleransı asla 2 dakikanın üzerine ayarlamayın. Daha fazlasına ihtiyacınız varsa bunun yerine NTP senkronizasyonunuzu düzeltin.
Hata #4: Yanlış Doğrulama Sırası
Doğru doğrulama sırası önemlidir. Sona erme tarihini kontrol ettikten sonra imzayı kontrol ederseniz, saldırgan zaman kontrolünden geçen ancak geçersiz bir imzaya sahip olan geleceğe yönelik bir exp ile bir belirteç oluşturabilir.
Güvenli doğrulama sırası:
- Kod çözme başlığı (algoritmayı kontrol et)
- İmzayı doğrulayın
- Kontrol edin
exp(süresi dolmuşsa reddet) - Kontrol edin
nbf(henüz geçerli değilse reddet) - Kontrol edin
iat(makul olmayacak kadar eskiyse reddet) - İhraççıyı, hedef kitleyi ve diğer talepleri kontrol edin
Bakımlı kitaplıkların çoğu bunu doğru bir şekilde ele alır, ancak özel ara yazılımlar sıklıkla bunu yanlış yapar.
Hata #5: iat
'de Saat Dilimi KarışıklığıJWT zaman damgaları her zaman UTC'dir. Ancak geliştiriciler bazen bunları yerel saati kullanarak oluşturur:
// WRONG — yerel saat dilimi
const iat = new Date('2026-03-27T14:00:00').getTime() / 1000; // DOĞRU — açık UTC
const iat = new Date('2026-03-27T14:00:00Z').getTime() / 1000;Z son eki olmadan, JavaScript dizeyi yerel saat diliminde yorumlar ve bu da zaman damgasını saat bazında değiştirebilir.
Hata #6: nbf Kontrolü Olmadan Tokenları Kabul Etme
nbf talebi, gecikmeli etkinleştirme belirteçleri için kullanışlıdır; örneğin, yalnızca planlanmış bir dağıtımdan sonra çalışması gereken bir belirteç. Doğrulayıcınız nbf'ü göz ardı ederse, bu jetonlar amaçlanan etkinleştirme sürelerinden önce kullanılabilir.
Çoğu kitaplık nbf öğesini varsayılan olarak doğrular, ancak bunu kurulumunuzda, özellikle özel ara yazılımla doğrulayın.
Hata #7: Aşırı Uzun Süre Sonu
Bir erişim belirteci için exp'nin 30 gün olarak ayarlanması, kısa ömürlü belirteçlerin amacını ortadan kaldırır. En iyi uygulamalar:
- Belirteçlere erişim: 5–15 dakika
- Jetonları yenile: 7–30 gün (rotasyonla)
- Kimlik jetonları: 1 saat
Güvenli yenileme jetonu kalıpları için JWT yenileme jetonu rotasyonu.
hakkındaki kılavuzumuza bakın.Her API'de Bulunması Gereken Test Senaryoları
Zaman talebi hatalarını erken yakalamak için bunları test paketinize ekleyin:
-
Geçmişte
- Token → 401
- Token ile
exptam olarak şimdi → 401 (sınır) - Token,
exp→ 401 içermeyen
- Gelecekte
nbfile belirteç → 401 - Token ile
nbfbiraz ileride (tolerans dahilinde) → 200 - Gelecekte
iatile belirteç → 401 (kurcalanmayı gösterir) - Milisaniyelik zaman damgalarına sahip belirteç → 401 (ms/s hatasını algılar)
exp ile Popüler Çerçeveler için Güvenli Varsayılanlar
Node.js (jsonwebtoken)
jwt.sign(yük, gizli, { expiresIn: '15m' });
jwt.verify(token, gizli, { clockTolerance: 30, maxAge: '15m'
});Python (PyJWT)
jwt.decode(belirteç, anahtar, algoritmalar=['HS256'], Leeway=timedelta(saniye=30), seçenekler={'require': ['exp', 'iat']})Git (golang-jwt)
parser := jwt.NewParser( jwt.WithLeeway(30 * time.Saniye), jwt.WithValidMethods([]string{"HS256"}),
)FAQ
Zorunlu olmalı mı?
JWT spesifikasyonu iat'nin isteğe bağlı olduğunu söylese de, zorunlu hale getirilmesi hata ayıklama ve denetim yollarına yardımcı olur. iat olmadan, bir belirtecin ne zaman oluşturulduğunu belirleyemezsiniz, bu da güvenlik olaylarıyla ilişkilendirmeyi zorlaştırır.
Saat sapmasına ne kadar izin vermeliyim?
Ortak güvenli varsayılan değer 30–60 saniyedir. 2 dakikadan fazla süre güvenlik riski doğurur. Sistemleriniz daha fazlasına ihtiyaç duyuyorsa çarpıklık payını genişletmek yerine NTP senkronizasyonunu düzeltin.
Süresi dolmuş bir jeton için hangi HTTP durum kodunu döndürmeliyim?
Return 401 Yetkisiz ve {"error": "token_expired"} gibi açık bir hata gövdesi ile. 403 Yasak'ı döndürmeyin — bu, belirtecin geçerli olduğu ancak izinlerin bulunmadığı anlamına gelir; bu da farklı bir durumdur.
İlgili Araçlar ve Makaleler
- JWT Kod Çözücü — herhangi bir belirteçteki zaman taleplerini inceleyin
- JWT Güvenlik Hataları — zaman iddialarının ötesinde daha geniş JWT tuzakları
- Token Rotasyonunu Yenile — uzun ömürlü oturumlar için güvenli model
- 2FA Kılavuzu — belirteçlerin ötesine ikinci bir katman ekleyin