JWT Yapısı ve Çalışma Prensibi
JWT (JSON Web Token), taraflar arasında güvenli bilgi transferi için kullanılan açık bir standarttır (RFC 7519). Stateless authentication için idealdir: sunucu session tutmaz, kullanıcıyla ilgili tüm bilgi token'ın kendisinde kodlanmıştır. Bu sayede sunucu herhangi bir state saklamadan her isteği bağımsız olarak doğrulayabilir.
Session-Based vs Token-Based Authentication
JWT'nin neden var olduğunu anlamak için iki yaklaşımı karşılaştıralım:
Session-Based (Geleneksel):
1. Kullanıcı login olur → Sunucu session oluşturur (bellekte/Redis'te)
2. Sunucu session ID'yi cookie ile gönderir
3. Her istekte cookie otomatik gider → Sunucu session'ı bellekten arar
4. Sorun: Sunucu her kullanıcı için state tutar → ölçekleme zor
Birden fazla sunucu varsa session paylaşımı gerekirToken-Based (JWT):
1. Kullanıcı login olur → Sunucu JWT üretir ve döner
2. Client token'ı saklar (localStorage, memory, cookie)
3. Her istekte Authorization: Bearer <token> gönderilir
4. Sunucu token'ı doğrular (signature check) — bellekte arama yok
5. Avantaj: Sunucu stateless → yatay ölçekleme kolay
Farklı sunuculara giden istekler sorunsuz çalışırJWT Yapısı: Header.Payload.Signature
Bir JWT, üç parçadan oluşur ve her parça nokta (.) ile ayrılır:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
\_________________________/\________________________/\__________________________________________/
HEADER PAYLOAD SIGNATUREHer parça Base64URL ile encode edilir. Base64URL, standart Base64'ten farklı olarak + yerine -, / yerine _ kullanır ve padding (=) eklemez — URL'lerde güvenle kullanılabilir.
1. Header
Header, token hakkında meta bilgi taşır:
{
"alg": "HS256",
"typ": "JWT"
}alg: Signature için kullanılan algoritma. Yaygın değerler:
- HS256 (HMAC-SHA256): Symmetric — aynı key ile imzalama ve doğrulama - RS256 (RSA-SHA256): Asymmetric — private key ile imzalama, public key ile doğrulama - ES256 (ECDSA-SHA256): Asymmetric — daha küçük key boyutu, aynı güvenlik
typ: Token türü, her zaman
"JWT"
2. Payload (Claims)
Payload, claim adı verilen bilgi parçalarını taşır. Üç tür claim vardır:
a) Registered Claims (Standart — RFC 7519):
| Claim | Açıklama | Örnek |
|---|---|---|
sub (subject) | Token'ın konusu — genellikle kullanıcı ID | "sub": "user-42" |
iss (issuer) | Token'ı oluşturan servis | "iss": "api.myapp.com" |
aud (audience) | Token'ın hedef kitlesi | "aud": "myapp-frontend" |
exp (expiration) | Son geçerlilik zamanı (Unix timestamp) | "exp": 1609462800 |
iat (issued at) | Oluşturulma zamanı | "iat": 1609459200 |
nbf (not before) | Bu zamandan önce geçersiz | "nbf": 1609459200 |
jti (JWT ID) | Token'ın benzersiz kimliği (replay koruması) | "jti": "abc-123" |
b) Public Claims (Kamuya Açık): IANA JWT Claims Registry'de kayıtlı veya URI ile tanımlanan claim'ler. Çakışmayı önler:
{
"email": "tolgahan@example.com",
"name": "Tolgahan",
"email_verified": true
}c) Private Claims (Özel): Uygulamaya özel, taraflar arasında anlaşılan claim'ler:
{
"sub": "user-42",
"roles": ["ROLE_USER", "ROLE_ADMIN"],
"department": "engineering",
"permissions": ["USER_CREATE", "REPORT_EXPORT"],
"iat": 1609459200,
"exp": 1609462800
}⚠️ Payload boyutu önemlidir: Her claim token boyutunu artırır. JWT her istekte gönderildiği için gereksiz claim'ler bandwidth harcar. Sadece ihtiyaç duyulan minimum bilgiyi koyun.
3. Signature (İmza)
Signature, token'ın bütünlüğünü garanti eder — herhangi bir manipülasyon tespit edilir:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey
)Doğrulama süreci:
Token'dan header ve payload'ı al
Aynı secret key ile signature'ı yeniden hesapla
Hesaplanan signature ile token'daki signature'ı karşılaştır
Eşleşmezse → token manipüle edilmiş, reddet
Symmetric vs Asymmetric Signing
| Özellik | Symmetric (HS256) | Asymmetric (RS256) |
|---|---|---|
| Key | Tek shared secret | Private + Public key çifti |
| İmzalama | Secret key ile | Private key ile |
| Doğrulama | Aynı secret key ile | Public key ile (secret gerekmez) |
| Kullanım | Tek servis (monolith) | Microservices, 3rd party doğrulama |
| Güvenlik | Key paylaşımı riski | Public key güvenle dağıtılabilir |
Microservices'te neden RS256? Auth Service private key ile token imzalar. Diğer tüm servisler (Order, Payment, Profile) sadece public key ile doğrulama yapar — secret'ı bilmelerine gerek yoktur.
JWT vs Opaque Token
| Özellik | JWT | Opaque Token |
|---|---|---|
| İçerik | Self-contained (bilgi taşır) | Rastgele string (bilgi taşımaz) |
| Doğrulama | Lokal (signature check) | Uzak (Auth Server'a sorma gerekir) |
| Boyut | Büyük (~800-2000+ byte) | Küçük (~32-64 byte) |
| Revocation | Zor (expiry'e kadar geçerli) | Kolay (DB'den sil) |
| Performans | Hızlı (network call yok) | Yavaş (her istekte introspection) |
| Ölçeklenme | Mükemmel (stateless) | Auth Server bottleneck olabilir |
Ne zaman JWT? Microservices, stateless API'ler, yatay ölçekleme gereken sistemler. Ne zaman Opaque? Anlık revocation kritik olan sistemler (bankacılık), basit monolith'ler.
JWT Güvenlik Riskleri ve Önlemleri
1. `alg: none` Attack: Saldırgan header'daki algorithm'i "none" yapıp signature'sız token gönderir. Kötü konfigüre edilmiş kütüphaneler bunu kabul edebilir.
// Saldırgan'ın token header'ı:
{ "alg": "none", "typ": "JWT" }Önlem: JJWT gibi modern kütüphaneler bunu varsayılan olarak reddeder. Yine de algoritma whitelist'i kullanın:
Jwts.parser()
.require("alg", "HS256") // Sadece HS256 kabul et
.verifyWith(secretKey)
.build();2. Token Theft (Token Çalınma): XSS ile localStorage'dan veya man-in-the-middle ile token çalınabilir. Önlem: HTTPS zorunlu, XSS koruması, kısa expiry, HttpOnly cookie veya memory storage.
3. Brute Force (Zayıf Secret Key): Kısa veya tahmin edilebilir secret key brute-force ile kırılabilir. Önlem: En az 256-bit (32 byte) rastgele key. Üretim için: openssl rand -base64 32
4. JWT Bilgi Sızıntısı: Payload şifrelenmez — Base64 decode eden herkes içeriği okuyabilir. Önlem: Hassas veri (şifre, kredi kartı, kişisel sağlık bilgisi) koymayın. Gerekiyorsa JWE (JSON Web Encryption) kullanın.
5. Token Replay: Çalınan geçerli token tekrar kullanılır. Önlem: Kısa expiry (15 dk), jti claim ile tek kullanımlık token'lar, IP/User-Agent binding.
Token Boyutu ve Performans
JWT her HTTP isteğinde Authorization header'ında gönderilir. Token büyüdükçe:
Bandwidth: Her istek ~1-3 KB ekstra taşır (session cookie ~32 byte)
Parsing: Her istekte Base64 decode + JSON parse + signature verify
HTTP Header Limiti: Çoğu web sunucusu header'ı 8KB ile sınırlar
Pratik öneriler:
Payload'a sadece
sub,roles,exp,iatgibi minimum bilgi koyunDetaylı kullanıcı bilgisini ayrı API ile çekin (userinfo endpoint)
Çok fazla role/permission varsa, bunları ID ile referans verin
⚠️ JWT payload'ı şifreli değildir — sadece Base64 encoded. Hassas bilgi (şifre, kredi kartı) koymayın! JWT'nin amacı gizlilik değil, bütünlük (integrity) ve kimlik doğrulamadır.
💡 Özet: JWT = Header.Payload.Signature, Base64URL encoded. Stateless authentication sağlar. Üç tür claim vardır: registered (iss, exp, sub), public ve private. Payload okunabilir — hassas veri koymayın. Symmetric (HS256) tek servis, asymmetric (RS256) microservices için uygundur. alg:none attack, token theft ve brute force gibi güvenlik risklerine karşı önlem alın.
AI Asistan
Sorularını yanıtlamaya hazır