JWT Decoder (Token Çözücü)
JWT header ve payload bilgisini tamamen tarayıcınızda çözün. Token hiçbir sunucuya gönderilmez. Türkçe karakter içeren claim değerlerini doğru çözer.
Bu araç yalnızca çözer, imzayı DOĞRULAMAZ. Çözülmüş bir token güvenilir bir token değildir; doğrulama için sunucu tarafında gizli anahtar veya açık anahtar gerekir.
Çözmek için bir token yapıştırın.
Özet (TL;DR)
- Çözmek doğrulamak değildir: çözülmüş bir token güvenilir bir token anlamına gelmez, imza kontrol edilmeden hiçbir claim'e karar verilmez.
- JWT segmentleri base64url ile kodlanır (
-ve_alfabesi, dolgu karakteri yok), bu yüzden çıplak atob() çoğu tokende ya patlar ya da yanlış çözer. - exp, iat ve nbf saniye cinsindendir; new Date(exp) size 1970 gösterir ve süre kararı ziyaretçinin cihaz saatine göre verilir.
- Bu araç tamamen tarayıcıda çalışır ve kasıtlı olarak "secret" alanı içermez; imzalama anahtarınızı hiçbir web sayfasına yapıştırmayın.
Çözmek doğrulamak değildir
Bir JWT üç parçadan oluşur ve bu parçaların ilk ikisi şifrelenmiş değildir, yalnızca kodlanmıştır. Yani token'ı elinde tutan herkes içeriğini okuyabilir. Bu aracın (ya da başka bir çözücünün) size gösterdiği şey, "bu token doğrudur" bilgisi değil, "bu token'ın içinde şunlar yazıyor" bilgisidir. Aradaki fark, bir güvenlik açığı ile düzgün bir kimlik doğrulama akışı arasındaki farktır.
İmzayı doğrulamak, token'ı üreten tarafın gizli anahtarını ya da açık anahtarını gerektirir. Bu iş sunucu tarafında, o anahtarın zaten bulunduğu yerde yapılır. Bu yüzden araçta bilinçli olarak bir "secret" giriş alanı yoktur: kullanıcılara imzalama anahtarlarını rastgele bir web sayfasına yapıştırmayı öğretmek, çözdüğü sorundan büyük bir sorun yaratır. Anahtarınız bir kere dışarı çıktığında, o anahtarla üretilebilecek her token artık taklit edilebilir demektir.
Uyarı
base64url ile base64 arasındaki fark
JWT segmentleri standart Base64 ile değil, RFC 4648'in URL güvenli varyantıyla kodlanır. İki fark vardır: + yerine -, / yerine _ kullanılır ve sondaki = dolgu karakterleri atılır. Sebep basit, token'lar URL'lerde, sorgu parametrelerinde ve HTTP başlıklarında taşınır; standart alfabenin karakterleri buralarda yeniden kodlanmak zorunda kalır.
const payload = token.split('.')[1]; // Yanlış: alfabe farklı, dolgu yokatob(payload);// InvalidCharacterError ya da sessizce bozuk çıktı // Doğru: önce alfabeyi normalize et, sonra dolguyu tamamlaconst normalized = payload.replace(/-/g, '+').replace(/_/g, '/');const padded = normalized.padEnd( normalized.length + ((4 - (normalized.length % 4)) % 4), '=');const binary = atob(padded);Uzunluğun 4'e bölümünden kalan 1 ise girdi hiçbir zaman geçerli Base64 olamaz, çünkü hiçbir kodlayıcı böyle bir çıktı üretmez. Bu durumda genellikle token kopyalanırken kırpılmıştır. Araç bu vakayı ayrı bir mesajla bildirir, çünkü atob'un kendi hatası ne olduğunu anlatmaz.
Türkçe karakterler ve atob tuzağı
Yukarıdaki kod parçasındaki binary değişkeni bir metin değil, bir ikili dizedir: her karakteri bir bayta karşılık gelir. Payload saf ASCII ise fark etmezsiniz. İçinde Türkçe bir isim geçtiği anda ise sonuç bozulur, çünkü UTF-8'de ü ve ş gibi karakterler iki bayt kaplar ve ikili dize bu iki baytı iki ayrı karakter gibi gösterir.
// atob çıktısı doğrudan metin sanılırsaatob('eyJhZCI6IkvDvHLFn2FkIn0');// '{"ad":"KürÅŸad"}' <-- mojibake // Baytları açıkça UTF-8 olarak çözmek gerekirconst bytes = Uint8Array.from(atob(padded), c => c.charCodeAt(0));new TextDecoder('utf-8').decode(bytes);// '{"ad":"Kürşad"}'Bu, Türkçe bir sistemde neredeyse her token'da karşınıza çıkar: kullanıcı adı, şehir, rol etiketi ya da özel bir claim içindeki herhangi bir Türkçe metin yeterlidir. Bu araç her segmenti TextDecoder ile çözer, dolayısıyla claim değerleri olduğu gibi görünür. Aynı hata JSON.parse aşamasına da taşınır: bozuk baytlar geçerli JSON üretebildiği için hata alınmaz, sadece yanlış veri görürsünüz.
Zaman claim'leri ve saat kayması
RFC 7519, exp, iat ve nbf claim'lerini NumericDate olarak tanımlar: 1 Ocak 1970'ten bu yana geçen saniye sayısı. JavaScript'in Date nesnesi ise milisaniye bekler. Değeri doğrudan geçirirseniz 1970 yılının ilk günlerinde bir tarih elde edersiniz ve bu, JWT araçlarının klasik hatasıdır.
| Claim | Anlamı | Yokluğunda ne olur |
|---|---|---|
| exp | Son geçerlilik anı (saniye) | Token'ın kendiliğinden sona erme zamanı yoktur, iptal listesi şarttır |
| iat | Üretilme anı (saniye) | Token yaşı hesaplanamaz, "çok eski" kontrolü yapılamaz |
| nbf | Bu andan önce geçersiz (saniye) | Token üretildiği anda geçerlidir |
| iss / aud | Üretici ve hedef kitle | Token başka bir servise ait olabilir, kapsam kontrolü kaybolur |
| jti | Benzersiz token kimliği | Tek kullanımlık iptal ve tekrar saldırısı takibi zorlaşır |
Bir noktayı da açıkça belirtmek gerekir: bu sayfada gördüğünüz "süresi dolmuş" kararı, sizin cihazınızın saatine göre verilir. Saati kaymış bir dizüstü bilgisayarda, gayet geçerli bir token süresi dolmuş görünebilir ya da tam tersi olabilir. Sunucular bu yüzden genelde birkaç dakikalık bir tolerans payı uygular. Beklenmedik bir sonuç aldığınızda önce sistem saatinizi kontrol edin.
JWS, JWE ve alg none
Nokta ile ayrılmış üç segment gördüğünüzde elinizde bir JWS vardır: başlık, yük ve imza. Beş segment gördüğünüzde ise bu bir JWE'dir ve segmentler başlık, şifrelenmiş anahtar, IV, şifreli metin ve doğrulama etiketidir. JWE'de yük gerçekten şifrelidir; alıcının çözme anahtarı olmadan hiçbir araç içeriğini gösteremez. Araç bu durumda yalnızca başlığı çözer ve sebebini açıkça söyler, anlamsız baytları ekrana basmaz.
Başlıkta alg değeri none ise, token imzasızdır. Spesifikasyonda yeri vardır ancak pratikte bu, herkesin istediği claim ile token üretebileceği anlamına gelir. Doğrulama katmanınız kabul edilecek algoritmaları açık bir listeyle sınırlamıyorsa, saldırgan imzayı silip alg değerini none yaparak kimlik doğrulamayı tamamen atlayabilir. Araç böyle bir token gördüğünde uyarı üretir.
Sıkça Sorulan Sorular
- Yapıştırdığım token bir sunucuya gönderiliyor mu?
- Hayır. Çözme işlemi tamamen tarayıcınızda çalışan JavaScript ile yapılır, token hiçbir ağ isteğine konu olmaz. Sayfa yüklendikten sonra internet bağlantınızı kesseniz bile araç çalışmaya devam eder. Yine de canlı ortamdan alınmış bir token'ı hata ayıklarken kullanmamak iyi bir alışkanlıktır.
- Neden imzayı doğrulayan bir alan yok?
- Doğrulama, imzalama anahtarını gerektirir ve o anahtar yalnızca sizin sunucunuzda bulunmalıdır. Bir web sayfasına secret yapıştırma alışkanlığı, aracın çözdüğünden çok daha büyük bir risk üretir. Doğrulamayı kendi ortamınızda, jsonwebtoken veya jose gibi bir kütüphaneyle yapın.
- Token'ın süresi dolmuş görünüyor ama sunucu kabul ediyor, neden?
- Süre kararı sizin cihazınızın saatine göre hesaplanır. Cihaz saatiniz ileri kaymışsa geçerli bir token süresi dolmuş görünür. Ayrıca sunucular genellikle birkaç dakikalık saat kayması toleransı uygular, dolayısıyla sınıra çok yakın token'larda iki taraf farklı karar verebilir.
- JWT içine hassas veri koyabilir miyim?
- Hayır. JWS yükü yalnızca base64url ile kodlanmıştır, şifrelenmemiştir; token'ı gören herkes okuyabilir. Gerçekten gizli kalması gereken veri için ya token'da sadece bir referans kimliği taşıyın ya da JWE kullanın. JWE'de yük şifrelidir ve bu araç da onu gösteremez.
- Token'ı çözdüm ama Türkçe karakterler bozuk çıkıyor, sorun nerede?
- Neredeyse her zaman atob çıktısının doğrudan metin sanılmasından kaynaklanır. atob bir ikili dize döndürür, bu yüzden iki bayt kaplayan Türkçe karakterler iki ayrı karakter gibi görünür. Baytları TextDecoder ile UTF-8 olarak çözmeniz gerekir. Bu araç zaten öyle yapar, dolayısıyla buradaki çıktı doğrudur.