İçeriğe geç
Utilerio

JWT Kimlik Doğrulama Gerçekte Nasıl Çalışır (ve Bir Token Nasıl Debug Edilir)

Bir JSON Web Token şifrelenmiş değil, imzalanmıştır — JWT hakkındaki kafa karışıklığının çoğunu açıklayan tek gerçek, artı bir token'ı debug etmek için pratik bir yöntem.

· 3 dk okuma

Bir JWT neredeyse her modern API'de Authorization: Bearer <token> başlığı olarak karşınıza çıkar ve genellikle opak bir blob gibi ele alınır — kopyala, yapıştır, çalışmasını um. Üç kısmını gerçekten anlamak için beş dakika ayırmaya değer, çünkü JWT hakkındaki en yaygın yanlış anlama — şifrelenmiş oldukları — aynı zamanda gerçek bir güvenlik hatasına en çok yol açabilecek olanıdır.

Noktalarla birleştirilmiş üç kısım

Bir JWT başlık.payload.imza şeklindedir; başlık ve payload JSON nesneleridir, her biri Base64url ile kodlanmıştır:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dGhpc2lzbm90YXJlYWxzaWduYXR1cmU
└──────────── başlık ────────────┘ └────────── payload ──────────┘ └────── imza ──────┘

Başlık, imzalama algoritmasını (alg) ve token türünü (typ) belirtir. Payload, claim'leri taşır — keyfi anahtar-değer verisi, artı bazı standart alanlar:

ClaimAnlamı
subSubject — genellikle kullanıcı id'si
issIssuer — token'ı kim oluşturdu
audAudience — token kimin için
iatVerildiği an, Unix zaman damgası
expSon kullanma, Unix zaman damgası
nbfBundan önce geçersiz, Unix zaman damgası

Herkesin yanlış anladığı kısım: şifreli değil, imzalı

Base64url bir kodlamadır, şifreleme değil — herhangi bir anahtar gerekmeden herkes tarafından tersine çevrilebilir. Bir JWT'ye sahip olan herkes, imzaya hiç dokunmadan onun tüm payload'ını okuyabilir. JWT Çözücü bunu doğrudan gösterir: başlığı ve payload'ı hiçbir secret olmadan çözer, çünkü çözülecek bir şifre yoktur.

İmzanın gerçekte yaptığı şey, sunucunun kurcalamayı tespit etmesini sağlamaktır: başlık ve payload üzerinden, yalnızca sunucunun bildiği bir secret kullanılarak hesaplanan bir HMAC'tir (ya da RSA/ECDSA imzasıdır). Payload'ın tek bir karakterini değiştirin, imza artık uyuşmaz — sunucu reddeder. Ama payload'ı token'a sahip kişiden asla gizlemez. Bu şu anlama gelir:

  • Bir JWT payload'ına asla bir şifre, bir API anahtarı veya hassas bir şey koymayın — token'a sahip olan herkes okuyabilir.
  • localStorage'da saklanan bir JWT, sayfada çalışan herhangi bir JavaScript tarafından okunabilir; bu da başarılı bir XSS saldırısını tam bir hesap ele geçirmeye dönüştürür. httpOnly çerez, tarayıcı oturumları için özellikle daha güvenli varsayılandır, çünkü istemci tarafı JavaScript onu okuyamaz.

Kısaca HS256 ile RS256

HS256 (HMAC-SHA256), imzalamak ve doğrulamak için tek bir paylaşılan secret kullanır — basittir, ama o secret'ın token'ı doğrulayan her serviste bulunması gerekir. RS256 bir RSA anahtar çifti kullanır: özel anahtar imzalar, genel anahtar doğrular; böylece bir servisin verdiği bir token, hiçbir secret paylaşılmadan birçok başka servis tarafından doğrulanabilir. HS256'nın imzası tam olarak bir anahtarla uygulanan bu hash fonksiyonu olduğu için, ham bir SHA-256 hash'inin gerçekte neye benzediğini görmek isterseniz Hash Üretici burada yararlı bir yardımcıdır.

Pratik bir debug yöntemi

  1. Önce çözün. Token'ı JWT Çözücü'ye yapıştırın ve exp'i şu anki zamanla karşılaştırın — süresi dolmuş bir token, "geçersiz token" hatasının en yaygın tek nedenidir ve koda hiç dokunmadan anında görülebilir.
  2. Claim'lerin sunucunuzun beklediğiyle eşleştiğini kontrol edin — mükemmel geçerli bir imzayla bile uyuşmayan bir aud veya eksik bir sub doğrulamayı başarısız kılar.
  3. Kendi tarafınızda yeniden üretin. Backend'iniz geçerli olması gerektiğini düşündüğünüz bir token'ı reddediyorsa, JWT Oluşturucu ile aynı başlık ve payload'a sahip, sunucunuzun yapılandırıldığı secret ile (HS256, HS384 veya HS512) imzalanmış bir token oluşturun ve sunucunun sizin sürümünüzü kabul edip etmediğine bakın. Kabul ediyorsa, orijinal token'ın secret'ı veya algoritması sunucunun beklediğiyle uyuşmuyor demektir.

Her iki araç da tamamen tarayıcınızda Web Crypto API ile çalışır — oluşturucuya yazdığınız bir secret yalnızca yerelde imzayı hesaplamak için kullanılır ve hiçbir yere gönderilmez; rastgele bir web sitesine yapıştırmak istemeyeceğiniz bir değer için bu önemlidir.

Bir taban daha: Base64'ün kendisi

Başlık ve payload segmentleri temelde Base64url olduğundan, elinizde JWT'ye özel bir araç yokken tek bir segmenti tam olarak neyin kodlandığını görmek için elle çözmek isterseniz Base64 Kodlayıcı / Çözücü hızlı bir yoldur.