Json Web Token, bilginin taraflar arasında güvenli bir biçimde taşınmasının, az maliyetli ve ek bir bağımlılığa ihtiyaç duymayan bir yoludur. Bu bilgi dijital olarak imzalandığı için güvenilebilir ve doğrulanabilir. Ayrıca authorization bilgilerini de tutabilir ki bu sayede her bir istek için veritabanına gidilerek kullanıcının rolleri ve izinleri için onaylama yapılmasına gerek kalmaz.
JWT üç bölümden oluşur: header, payload ve signature.
Header, token tipini, imzalama algoritmasını barındıran bir Json nesnesidir. Base64url (byte veri text olarak görüntülenir) kodlanmıştır(encode). Decode görünümü ;
{
"alg": "HS256",
"typ": "JWT
}
Payload kısmı, kullanıcı ve kimlik doğrulama olayı (authentication) hakkında bilgileri tutan veri taleplerini (data claims) içeren bir Json nesnesidir.
Sub (Subject): Kullanıcının kimliğini tanımlar. Örneğin, kullanıcı adı veya bir kullanıcı ID’si olabilir.
Iss (Issuer): JWT’yi oluşturan tarafın (issuer) kimliğini belirtir.
Exp (Expiration Time): JWT’nin geçerlilik süresini belirtir.
Nbf (Not Before): JWT’nin kullanılmaya başlanabileceği tarihi belirtir.
Iat (Issued At): JWT’nin oluşturulma tarihini belirtir.
Base64url kodlanmıştır. Bu bilgi şifrelenmediği için, sadece encode edildiği için gizli değildir, görülebilir. Decode hali örneğin:
{
"sub": "91287346",
"name": "Kullanici Adi",
"iat": 751641011
}
Üçüncü bölüm signature (imza) kısmıdır. JWT’ler iletilirken değiştirilemez olmaları için imzalanırlar.
JWT oluşturulurken birinci ve ikinci kısım Base64url encode edilirler ve ‘.’ ile birleştirilirler. base64urlEncode(header)+”.”+base64urlEncode(payload).
Bu iki kısım birleşerek bir veri seti oluşur.
Bu veri seti, belirtilen algoritma (örneğin, HMACSHA256) ve gizli anahtar (secret key) kullanılarak doğrudan imzalanır. Burada iki aşamalı bir süreç işler.
İlk aşamada veri seti (birleşmiş kısım) SHA-256 algoritması ile hash’lenir.
özet = SHA-256(veriSeti)
Hash’leme bir değeri başka bir değere dönüştürür. Hash işlemi tek yönlüdür, hashlenmiş değer kullanılarak input değerine geri dönülemez. Aynı input kullanılarak yapılan hashleme işlemi her durumda aynı output’u verir.
İkinci aşama ise ilk aşamada elde edilen hashlenmiş değerin bir gizli anahtar kullanılarak şifrelenmesidir.
imza = HMACSHA256(özet(hash), secret).
imza işlemi jjwt-impl-0.11.5.jar içinde, io.jsonwebtoken.impl paketi içindeki DefaultJwtBuilder sınıfında şu şekilde gerçekleşir:
JwtSigner signer = createSigner(algorithm, key);
String base64UrlSignature = signer.sign(jwt);
byte array şeklinde elde edilen imza base64UrlEncode ile base64UrlSignature haline döndürülür. Dönen imza değeri String olur bu şekilde.
İmza, JWT’nin signature kısmını oluşturur.
İlk üretilen iki kısım vardır. Onlara veri seti demiştik. Şimdi onların sonuna da bu bu JWT signature (imza) ‘.’ kullanılarak eklenir. Artık JWT oluşturulmuş olur. Kullanıcı bundan sonra yapacağı her istek için Http Authentication Header içinde JWT’yi de sunucuya gönderir.
Sunucu gelen JWT için validasyon yaparken öncelikle header ve payload kısımlarının encoded hallerini alır. Bunları yeniden SHA-256 ile hash’ler. Sonra sunucu tarafında tutulan gizli anahtar ile tekrar imzalama işlemi yapılır.
tekrarImza = HMACSHA256(özet(hash), secret)
Elde edilen tekrarImza, gelen JWT’nin içindeki imza ile karşılaştırılır. Eğer imzalar eşleşiyorsa ve token’ın expiration time değeri dolmadıysa yani yeterli ömrü varsa, JWT geçerli olarak kabul edilir.