Kurumsal web uygulamalarında JWT ile kimlik doğrulama: Access token, refresh token rotasyonu, HttpOnly cookie güvenliği ve XSS önleme kılavuzunu okuyun.
Hızlı Özet (TL;DR)
JWT (JSON Web Token — RFC 7519), mikroservis mimarilerinde, modern SPA (Single Page Application) arayüzlerinde ve endüstriyel B2B/ERP portallarında durumsuz (stateless) kimlik doğrulama için endüstri standardıdır. Ancak geliştiricilerin kolaylık olsun diye JWT’leri tarayıcının localStorage veya sessionStorage alanında saklaması, olası bir XSS (Cross-Site Scripting) zafiyetinde kullanıcının oturum anahtarının saniyeler içinde çalınmasına yol açar. Güvenli bir kurumsal kimlik doğrulama mimarisi; yalnızca bellekte (In-Memory) tutulan kısa ömürlü (5–15 dakika) bir Access Token ile istemciye yalnızca HttpOnly, Secure ve SameSite=Strict bayraklı çerezler üzerinden teslim edilen uzun ömürlü (7–30 gün) bir Refresh Token ikilisinden oluşur. Ayrıca her yenileme işleminde eski Refresh Token geçersiz kılınmalı ve Token Rotasyonu (Refresh Token Rotation) ile tekrar kullanım tespiti (Reuse Detection) uygulanmalıdır.
Kurumsal Yazılımlarda Session ID’den JWT Mimarisine Geçiş
Geleneksel monolitik web uygulamalarında kullanıcı giriş yaptığında sunucu belleğinde veya merkezi veritabanında bir oturum kaydı (Session ID) oluşturulur ve her HTTP isteğinde veritabanına gidilerek bu oturumun geçerliliği sorgulanırdı. Ancak bugün bir fabrikanın İmalat ERP Çözümleri altyapısında aynı anda hem masaüstü web tarayıcıları, hem depodaki el terminalleri, hem sahadaki dokunmatik kiosk paneller hem de tedarikçi EDI servisleri API uç noktalarına saniyede yüzlerce istek göndermektedir.
Her API çağrısında merkezi veritabanına SELECT * FROM sessions sorgusu atmak ciddi bir darboğaz (bottleneck) yaratır. JWT mimarisi bu sorunu kriptografik imza ile çözer: Sunucu, kullanıcının kimliğini (sub), rollerini (roles) ve geçerlilik süresini (exp) JSON formatında imzalayarak istemciye verir. API Gateway veya mikroservisler, veritabanına sormadan yalnızca kriptografik imzayı doğrulayarak milisaniyenin altında yetkilendirme kararı verebilir.
JWT’nin Üç Katmanlı Yapısı: Header, Payload ve Signature
Bir JWT, noktalarla ayrılmış üç Base64URL kodlu diziden (xxxxx.yyyyy.zzzzz) oluşur:
- Header (Başlık): Token tipini (
JWT) ve kullanılan imzalama algoritmasını (HS256,RS256veyaES256) belirtir. - Payload (Veri Yükü / Claims): Kullanıcı kimliği (
sub), token’ın üretildiği zaman (iat), son kullanma tarihi (exp), hedef kitle (aud) ve yetki kapsamları gibi standart veya özel (custom) alanları barındırır. - Signature (Kriptografik İmza): Header ve Payload birleştirilerek sunucunun gizli anahtarıyla (Secret Key veya Private Key) özetlenir. Payload içindeki bir karakter bile yetkisizce değiştirilirse (örneğin
role: "operator"ifadesirole: "admin"yapılırsa) imza doğrulaması anında başarısız olur.
Access Token ve Refresh Token Yaşam Döngüsü
Tek bir token kullanarak hem güvenliği hem de kullanıcı deneyimini aynı anda sağlamak imkansızdır: Token süresini 15 dakika yaparsanız kullanıcı her 15 dakikada bir şifre girmek zorunda kalır; süreyi 30 gün yaparsanız çalınan bir token 30 gün boyunca iptal edilemez. Bu ikilemi çözmek için görev ayrımı yapılır:
| Kriter | Access Token (Erişim Anahtarı) | Refresh Token (Yenileme Anahtarı) |
|---|---|---|
| Kullanım Amacı | Korunan API uç noktalarına (GET /orders, POST /production) yetkili istek yapmak | Süresi dolan Access Token’ı kullanıcıya şifre sormadan arka planda yenilemek |
| Geçerlilik Süresi (TTL) | 5 – 15 Dakika (Çok kısa ömürlü) | 7 – 30 Gün (Uzun ömürlü, oturum süresini belirler) |
| İstemcide Saklama Yeri | Uygulama Belleğinde (In-Memory / JS Değişkeni / State) | HttpOnly, Secure, SameSite=Strict Çerez (Cookie) |
| Veritabanı / Durum Takibi | Durumsuz (Stateless) — İmza doğrulaması yeterlidir | Durumlu (Stateful) — Hash’lenmiş hali Redis veya SQL’de tutulur |
| Çalınma ve XSS Riski | localStorage’a yazılmadığı için kalıcı çalınamaz; sızsa dahi 15 dk içinde ölür | JavaScript (document.cookie) tarafından kesinlikle okunamaz (XSS korumalı) |
| İptal Edilebilirlik (Revocation) | Süresi dolana kadar kendi kendine geçersizleşir | Sunucu tarafındaki tablodan silinerek anında iptal edilebilir |
Token Rotasyonu (Refresh Token Rotation) ve Hırsızlık Tespiti
Refresh Token’ın HttpOnly çerez içinde saklanması JavaScript tabanlı XSS saldırılarını engellese de, ağ dinlemesi veya zararlı tarayıcı eklentileri gibi uç senaryolara karşı OAuth 2.0 Güvenlik En İyi Uygulamaları (RFC 6819 / BCP) kapsamında Refresh Token Rotation mekanizması uygulanmalıdır.
Bir kullanıcı yeni bir Access Token talep ettiğinde sunucu yalnızca yeni bir Access Token üretmekle kalmaz; mevcut Refresh Token’ı tek kullanımlık kabul ederek iptal eder ve istemciye yepyeni bir Refresh Token teslim eder:
- Sessiz Yenileme (Silent Refresh): İstemci süresi dolmuş Access Token ile API’ye istek atar ve
401 Unauthorizedyanıtı alır. - Güvenli Çerez Gönderimi: İstemci tarafındaki HTTP Interceptor (örneğin Axios veya Fetch sarmalayıcısı) otomatik olarak
POST /api/auth/refreshuç noktasına istek gönderir. Tarayıcı, yalnız bu yola (Path=/api/auth/refresh) kısıtlanmışHttpOnlyçerezi otomatik olarak isteğe ekler. - Token Ailesi (Token Family) Güncellemesi: Sunucu gelen Refresh Token’ın veritabanındaki özetini (SHA-256 hash) kontrol eder, kullanıldı olarak işaretler ve aynı “Token Ailesi” (Family ID) altında yeni bir Access + Refresh Token çifti döner.
- Tekrar Kullanım Tespiti (Reuse Detection / Hırsızlık Koruması): Eğer saldırgan daha önce bir şekilde eski Refresh Token’ı ele geçirmişse ve bu eski token ikinci kez kullanılmaya çalışılırsa, sunucu “Kullanılmış bir token tekrar geldi!” alarmı üretir. Bu durumda o Token Ailesine ait tüm aktif oturumlar anında iptal edilir (Invalidate) ve gerçek kullanıcıdan yeniden şifre ve MFA ile giriş yapması istenir.
En Sık Yapılan 5 Kritik JWT Güvenlik Hatası
Kurumsal sızma testlerinde (Pentest) ve kod denetimlerinde geliştiricilerin en sık düştüğü kimlik doğrulama tuzakları şunlardır:
1. Hassas Verileri Payload İçine Koymak
JWT şifrelenmiş (encrypted - JWE) değil, yalnızca imzalanmış (signed - JWS) bir yapıdır. Base64URL formatındaki payload kısmı herhangi bir kişi tarafından atob() fonksiyonuyla düz metin olarak okunabilir. Parola özetleri, T.C. kimlik numaraları, özel maliyet katsayıları veya kişisel veriler asla JWT payload içine yazılmamalıdır.
2. “alg: none” Zafiyeti ve Algoritma Karıştırma Saldırıları
Sunucu tarafındaki JWT doğrulama kütüphanelerinde kabul edilen algoritma açıkça beyaz listeye alınmalıdır (algorithms: ['RS256']). Eğer kütüphane token’ın kendi başlığındaki alg değerine körü körüne güvenirse, saldırganlar başlığı {"alg": "none"} yaparak imzasız sahte yönetici token’ı üretebilir veya asimetrik açık anahtarı (Public Key) simetrik HMAC gizli anahtarı gibi kullanarak imzayı taklit edebilirler.
3. Zayıf Simetrik Anahtarlar (HS256 Brute-Force)
Eğer imzalama için simetrik HS256 algoritması kullanılıyor ve gizli anahtar olarak "secret123" veya "maysa2026" gibi tahmin edilebilir kısa kelimeler seçiliyorsa, saldırganlar eldeki herhangi bir geçerli JWT üzerinde çevrimdışı (offline) ekran kartlarıyla saniyede milyarlarca deneme (hashcat) yaparak gizli anahtarı kırabilir. Kurumsal sistemlerde en az 256 bitlik kriptografik rastgele anahtarlar veya RS256 / ES256 (Asimetrik Açık/Özel Anahtar) mimarisi tercih edilmelidir.
4. localStorage Kullanımı ve Üçüncü Parti NPM Paket Riski
Modern ön yüz projelerinde onlarca açık kaynak NPM paketi kullanılır. Bu paketlerden yalnızca birinde oluşacak bir tedarik zinciri (Supply Chain) saldırısı veya XSS açığı, window.localStorage.getItem('token') komutuyla tüm kullanıcıların anahtarlarını dışarı sızdırabilir.
5. Denetim İzi (Audit Log) Eksikliği
Başarılı ve başarısız giriş denemeleri, token yenileme hataları ve yetki yükseltme girişimleri IP adresi, cihaz parmak izi (User-Agent) ve zaman damgasıyla birlikte KVKK 5651 Yasal Loglama standartlarına uygun olarak kayıt altına alınmalıdır.
Güvenli, OWASP Top 10 uyumlu ve rol tabanlı yetkilendirmeye (RBAC) sahip modern kurumsal uygulamalar geliştirmek için Özel Yazılım Geliştirme ve yüksek performanslı Web Sayfası Tasarım hizmetlerimizden faydalanabilirsiniz.
Sıkça Sorulan Sorular
Access Token bellekte (In-Memory) tutulduğunda kullanıcı sayfayı yenilerse (F5) oturum düşer mi?
Hayır, oturum düşmez. Kullanıcı tarayıcıda F5 tuşuna bastığında JavaScript belleği sıfırlanır ancak tarayıcıdaki HttpOnly Refresh Token çerezi yerinde durmaktadır. Uygulama ilk açılırken (Bootstrap aşamasında) arka planda sessizce /api/auth/refresh uç noktasına bir istek atar, milisaniyeler içinde yeni Access Token’ı belleğe alır ve kullanıcı hiçbir kesinti hissetmeden çalışmaya devam eder.
Mikroservis mimarisinde HS256 mı yoksa RS256 mı tercih edilmelidir?
Kesinlikle RS256 veya ES256 (asimetrik imzalama) tercih edilmelidir. Simetrik HS256 kullanıldığında, token üreten Kimlik Doğrulama Servisi (Auth Service) ile token’ı doğrulayan tüm diğer mikroservislerin aynı gizli anahtarı (Secret Key) paylaşması gerekir; bu da servislerden biri ele geçirildiğinde tüm sistemin tehlikeye girmesi demektir. Asimetrik RS256 mimarisinde ise Özel Anahtar (Private Key) yalnızca Auth sunucusunda durur, diğer tüm servisler sadece Açık Anahtar (Public Key / JWKS) ile doğrulama yapar; yeni token üretemezler.
Kullanıcının yetkisi alındığında veya işten çıkarıldığında 15 dakikalık Access Token nasıl anında iptal edilir?
Çok kritik işlemlerde (örneğin banka para transferi, ERP’de toplu stok silme veya savunma sanayii doküman indirme) 15 dakikalık bekleme süresi bile kabul edilemez. Bunun için bellek içi çok hızlı bir önbellek olan Redis Blacklist (Kara Liste) kullanılır. Kullanıcı engellendiğinde kimliği (sub veya token ID jti) kalan geçerlilik süresi (TTL = 15 dk) boyunca Redis’e yazılır ve API Gateway bu kara listeyi kontrol ederek erişimi saniyesinde keser.