JWT (JSON Web Tokens) Nedir? Ne işe yarar?
JWT (JSON Web Tokens), IETF kuruluşu tarafından tasarlanan standart bir token biçimidir (Bkz. RFC 7519). Haberleşen iki veya daha fazla sistem (Web, Mobile, IOT, Cloud vb.) arasında kullanıcı doğrulama, kullanıcı tanıma, veri bütünlüğünü ve bilgi güvenliğini koruma gibi noktalarda kullanılmaktadır.
JWT’nin avantajları
-
JSON kullanması
-
URL üzerinde taşınabilmesi
-
Web çerezleri kullanma zorunluluğu olmaması
-
CSRF ataklarına karşı daha kapalı olması
-
Hızlı doğrulama yapılabilmesi
-
Kolay ölçeklenebilir olması
-
Web uygulamaları açısından HTTP session gerekmemesi, stateless kullanıma uygun olması
-
Veri bütünlüğünü sağlaması
JWT’nin yapısı
JWT, Base64 biçiminde kodlanmış 3 ayrı JSON parçasından oluşmaktadır. Parçalar nokta (.) sembolüyle ayrılmakta ve bir bütün olarak JWT’yi temsil etmektedir.
JOSE Header
JWT başlık bilgisi JSON biçiminde yazılmakta ve standart bazı alanları bulunmaktadır. Aşağıda genel bir örneğini görmektesiniz.
{
"alg": "HS256", (1)
"typ": "JWT" (2)
}
1 | Veri bütünlüğünü korumak için kullanılacak cryptotic algoritmayı belirtir. |
2 | Bir JWT nesnesi olduğunu belirtir |
JOSE başlığı token içine eklenirken Base64 biçiminde kodlanır. Örneğin yukarıdaki JSON başlığın Base64 karşılığı ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9
dir. JWT’nin URL dostu oluşu Base64 gösterimini kullanmasından kaynaklanmaktadır.
JWT Payload
Bir JWT token, bir token üretici ve tüketicisi arasında eşsiz olmalıdır. Bu eşsizliği payload diğer adıyla claim bilgileri tanımlar. Payload içinde kullanıcıya ait kimlik, zaman aşımı ve kullanıcı yetkileri gibi alanlar yer alabilir.
{
"userId": "3344552266",
"expire": 1486220816,
"roles": ["admin", "user"]
}
Örneğin yukarıdaki JWT payload içindeki userId
alanı eşsiz kullanıcı kodunu, expire
token zaman aşımı anını, roles
ise kullanıcı yetkilerini temsil etmektedir. Bir token içinde expire
alanı olması zorunlu değil, yine roles
alanı olması da zorunlu değil fakat eşsizlik ve aidiyeti temsil etmek için userId
gibi bir alan olması gerekiyor.
Payload içine ne koyulacağı tamamen geliştiricisine bağlı fakat RFC 7519 birtakım isteğe bağlı alan adını standartlaştırmıştır. İsterseniz bu standart isimlendirmeleri kullanabilirsiniz (Bkz. rfc7519#page-9).
Payload JWT token içine eklenirken aynı JOSE başlığında olduğu gibi Base64 biçiminde kodlanır. Yukarıdaki başlığın Base64 karşılığı ewogICJ1c2VySWQiOiAiMzM0NDU1MjI2NiIsCiAgImV4cGlyZSI6IDE0ODYyMjA4MTYsCiAgInJvbGVzIjogWyJhZG1pbiIsICJ1c2VyIl0KfQ==
dir.
JWT Signature (JWT İmzası)
3 parçadan oluşan JWT’nin son parçası JWT imzasıdır. İmza kısmı token üreticisi ve tüketicisi arasındaki veri bütünlüğünü garanti etmektedir. İmza oluşturulurken JOSE başlığında tanımlı algoritma kullanılmaktadır.
JWT imzası, JWT başlığı ve JWT payload birleştirilerek aşağıda sıralı adımlarla oluşturulmaktadır.
Base64 kodlaması için temsili |
PART1= doBASE64(HEADER) PART2= doBASE64(PAYLOAD) PART1_PART2= PART1 + "." + PART2 SECRET_KEY= "Merhaba KodEdu" PART3= doBASE64(doHMACSHA256(PART1_PART2, SECRET_KEY)) JWT_TOKEN= PART1_PART2 + "." + PART3
Gizli anahtar (Secret Key) HS256 algoritması için kullanılmaktadır. doHMACSHA256 fonksiyonu, imzalanacak veriyi (PART1_PART2) tanımladığınız anahtarla imzalayarak imza kısmını oluşturur. Veri bütünlüğünün bozulup bozulmadığı ise yine bu fonksiyon ve gizli anahtar ile sorgulanır.
Yukarıdaki işlemler sonucunda JWT token çıktımız aşağıdaki gibi olacaktır.
ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9.ewogICJ1c2VySWQiOiAiMzM0NDU1MjI2NiIsCiAgImV4cGlyZSI6IDE0ODYyMjA4MTYsCiAgInJvbGVzIjogWyJhZG1pbiIsICJ1c2VyIl0KfQ==.K0VLcjhVQWZMem0yMnF1L280QktFRUZNZ3VHTVNQLzNrVFlMSmMzNjQ5QT0=
Üretilen JWT bilgisini https://jwt.io/ adresinden test edebilirsiniz. |
JWT’nin doğrulanması
JWT doğrulamak için, doğrulanacak JWT token nokta (.) ayraçlarından 3 parçaya bölünerek PART1
, PART2
ve PART3
olarak ayıklanır. Ardından PART1, PART 2 ve sadece bizim bildiğimiz SECRET_KEY ile yukarıdaki adımlarla JWT imzası hesaplanır. Hesaplanan JWT imzası ile ayıklanan PART3
aynı ise JWT token doğrulanmış olur. Aynı değilse token geçersiz demektir.
JWT’nin uygulanışı
JWT standardını uygulayan birçok açık kaynak kütüphane bulunmakla birlikte, bu yazıda sizlerle JWT için yukarıda bahsedilen adımları uygulayan bir örneği paylaşmak istiyorum.
public String doHMACSHA256(String part1AndPart2, String secretKey){
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
byte[] hashBytes = mac.doFinal(part1AndPart2.getBytes());
String hash = doBASE64(hashBytes);
return hash;
}
public String doBASE64(byte[] bytes) {
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(bytes);
return base64;
}
public String doBASE64(String input) {
byte[] bytes = input.getBytes(Charset.forName("UTF-8"));
String base64 = doBASE64(bytes);
return base64;
}
public String generateJWT(){
String HEADER = String.join("\n", Files.readAllLines(Paths.get("./header.json")));
String PAYLOAD = String.join("\n", Files.readAllLines(Paths.get("./payload.json")));
String PART1 = doBASE64(HEADER);
String PART2 = doBASE64(PAYLOAD);
String PART1_PART2 = PART1 + "." + PART2;
String PART3 = doBASE64(doHMACSHA256(PART1_PART2, SECRET_KEY));
String JWT_TOKEN = PART1_PART2 + "." + PART3;
return JWT_TOKEN;
}
public boolean validateJWT(String jwt) {
String[] parts = jwt.split("\\.");
String PART1 = parts[0];
String PART2 = parts[1];
String PART3 = parts[2];
String PART1_PART2 = PART1 + "." + PART2;
String jwtSignature = doBASE64(doHMACSHA256(PART1_PART2, SECRET_KEY));
return jwtSignature.equals(PART3);
}
String JWT_TOKEN = generateJWT();
boolean isValid = validateJWT(JWT_TOKEN);
System.out.println("Is valid ? " + isValid);
Uygulama kodlarına https://github.com/rahmanusta/JwtDemo adresinden erişebilirsiniz.
Faydalı olması dileğiyle.
4 Comments
Merhaba, yazınız için teşekkür ederim. JWT’nin Türkçe olarak anlaşılması için çok güzel bir kaynak.
JWT Payload örneği kısmında, user’ın başka bilgilerini de kullanmaya çalıştığımda hata aldım. Bu bilgilerden hangileri kullanılabilir ? userMail bunun için kullanılabilir mi ?
Teşekkürler.
İyi Çalışmalar.
Merhaba, kullanmadınızda bir sakınca bulunmuyor. Paylaşılan kodu modifiye ederek deneyebilirsiniz.
Selamlar, JWT hakkında temel bilgilere bu makale sayesinde ulastım. Tesekkürler Rahman.