← Kursa Dön
📄 Text · 20 min

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ı gerekir

Token-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ışır

JWT 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                         SIGNATURE

Her 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):

ClaimAçı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:

  1. Token'dan header ve payload'ı al

  2. Aynı secret key ile signature'ı yeniden hesapla

  3. Hesaplanan signature ile token'daki signature'ı karşılaştır

  4. Eşleşmezse → token manipüle edilmiş, reddet

Symmetric vs Asymmetric Signing

ÖzellikSymmetric (HS256)Asymmetric (RS256)
KeyTek shared secretPrivate + Public key çifti
İmzalamaSecret key ilePrivate key ile
DoğrulamaAynı secret key ilePublic key ile (secret gerekmez)
KullanımTek servis (monolith)Microservices, 3rd party doğrulama
GüvenlikKey paylaşımı riskiPublic 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

ÖzellikJWTOpaque Token
İçerikSelf-contained (bilgi taşır)Rastgele string (bilgi taşımaz)
DoğrulamaLokal (signature check)Uzak (Auth Server'a sorma gerekir)
BoyutBüyük (~800-2000+ byte)Küçük (~32-64 byte)
RevocationZor (expiry'e kadar geçerli)Kolay (DB'den sil)
PerformansHızlı (network call yok)Yavaş (her istekte introspection)
ÖlçeklenmeMü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, iat gibi minimum bilgi koyun

  • Detaylı 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.