JWT (JSON Web Token), genellikle kimliği doğrulanmış bir kullanıcı hakkında imzalanmış verileri iletmek için kullanılan kompakt bir formattır. Bir token, noktalarla ayrılmış üç bölümden oluşur: header.payload.signature. Türk yazılım ekosisteminde .NET ve Java/Spring backend'lerinde JWT tabanlı kimlik doğrulama oldukça yaygındır.
"I" harfi problemi claim anahtarlarında nasıl hataya yol açar
Türkçede küçük "i"nin büyük hâli noktalı "İ", küçük "ı"nın büyük hâli ise noktasız "I"dır. Bir geliştirici, gelen bir JWT'nin claim anahtarını (örneğin "id") Türkçe kültür ayarlarıyla büyük harfe çevirirse, sonuç beklenen "ID" değil "İD" olabilir — bu da JSON anahtarlarını birebir karşılaştıran kodun sessizce claim'i bulamamasına yol açan, saf Türkçe geliştirici ekiplerinin sıkça karşılaştığı klasik bir hatadır. Çözüm, anahtar karşılaştırmalarında her zaman kültürden bağımsız (invariant) büyük/küçük harf dönüşümü kullanmaktır.
Bir tokenin üç bölümü
- Header — token türünü ve imza algoritmasını (örneğin HS256 veya RS256) içeren, Base64URL ile kodlanmış bir JSON.
- Payload — "claim"leri içeren bir JSON: kullanıcı verileri, verilme zamanı, geçerlilik süresi vb., o da Base64URL ile kodlanmış.
- Signature — header ve payload üzerinden gizli veya özel bir anahtarla hesaplanan, tokenin değiştirilmediğini doğrulayan bir imza.
Base64URL, normal Base64 değil
JWT, URL için güvenli bir Base64 alfabesi varyantı kullanır: + ve / karakterleri - ve _ ile değiştirilir ve = dolgu genellikle atlanır. Bu, tokenin ek kodlama yapmadan bir URL'ye veya başlığa yerleştirilebilmesini sağlar.
Önemli bir ayrım: çözmek ≠ doğrulamak
Header ve payload sadece Base64URL'dir — herkes bunları herhangi bir anahtar olmadan çözebilir ve içeriğini okuyabilir. Bir tokenin içeriğine ancak uygun anahtarla imzası doğrulandıktan sonra güvenilebilir — ve bu doğrulamayı sunucu yapar, token içindeki verilere sadece bakan bir istemci değil.
Tehlikeli bir saldırı: algoritmayı "none" ile değiştirmek
JWT spesifikasyonu, imzasız bir token anlamına gelen none algoritmasına izin verir. Bir backend, sabit ve önceden bilinen bir algoritmaya göre imzayı doğrulamak yerine token başlığındaki alg alanına saf bir şekilde güvenirse, saldırgan alg değerini none ile değiştirip imzayı kaldırabilir. Güvenilir JWT kütüphaneleri, doğrulama sırasında beklenen algoritmanın açıkça belirtilmesini zorunlu kılar.
Türkçe karakterler claim değerlerinde
"Şehir": "İzmir" gibi bir claim değeri Base64URL'e kodlanırken sorun çıkarmaz — kodlama UTF-8 baytları üzerinde çalışır. Ancak ç, ğ, ı, ö, ş, ü gibi harflerin her biri UTF-8'de 2 bayt kapladığından, Türkçe kullanıcı adı ve şehir bilgisi içeren bir token, tamamen ASCII olan bir eşdeğerinden biraz daha uzun olur.