Komplike tanımlara girmeden basitçe ifade etmek gerekirse; JSON Web Token (JWT), taraflar arası güvenli bir şekilde JSON olarak veri aktarımı yapılmasını sağlayan bir standarttır.
Genellikle kullanıcı kimliklendirme işlemlerinde kullanılır. Bu kimliğin doğrulanması sırasında herhangi farklı bir sunucuya gitme ihtiyacı olmaz. Aynı şekilde veri tabanından da sorgulama yapmasına gerek kalmaz. Sunucuya gelen token bilgisi kod tarafında doğrulanır ve kullanıcıya talep ettiği içerik sunulur. Basit anlamdaki kullanımı bu şekildedir.
Diğer alternatiflerine göre daha küçük boyutludur. Bu sebeple bir JWT’yi URL üzerinden, POST parametresi olarak ya da HTTP header’a koyarak hızlıca sunucuya gönderebiliriz.
Neden JWT?
JWT diğer alternatiflerine göre JSON kullandığı için daha kompakt bir yapıdadır. Bu sebeple alternatiflerinin kullandığı XML yapısına nazaran, HTTP ortamında JWT’nin transferi daha kolay şekilde gerçekleşmektedir.
Çoğu programlama dilinde JSON’a özel parserlar bulunmaktadır. Geliştiriciler bu anlamda daha kolay parse edilen JSON verisini tercih edeceklerdir. XML’in aksine JSON verisi programlama dilinde kullanılan objelere de kolayca maplenebilirler.
Oturum yönetiminde çerez veya session kullanma ihtiyacı yoktur. Bir JWT’yi alıp localStorage’a atarak kullanabilirsiniz.
Bir JWT ile birden fazla domain üzerinde kullanılarak kimliklendirme işlemleri yapılabilir, Single Sign-On (SSO) mekanizmalarında kullanılabilir.
JSON Web Token’ın Yapısı
Bir JWT noktalarla ayrılmış üç parçadan oluşur.
Örnek bir JWT üzerinden kontrol ettiğimizde ilk kısım [Header], ortadaki [Payload] ve son kısım ise [Signature] bölümüdür. Şimdi kısaca bu terimlerin üzerlerinden geçelim.
Header
Başlık bölümü, JWT’nin imza bölümünde kullanılan algoritma ve token türü gibi bazı bilgiler içeren JSON sözdizimidir. JWT için bir header bilgisinin decode hali şu şekildedir;
{ "alg": "HS256", "typ": "JWT" }
Bu örnekteki HS256 değeri imzayı oluşturmak için kullanılacak olan HMAC SHA-256 algoritmasıdır. JWT oluşturulurken bu veri Base64Url ile encode edilecektir.
Payload
Bir varlığın (bu genellikle kullanıcı bilgisi olur) claim adı verilen bilgilerini içerir. Claim kelimesi bir konu hakkındaki ileri sürülen bilgi parçası anlamına geliyor. Buradaki kullanımı ise, kullanıcı hakkında bilgiler vermesi ve JWT doğrulaması yapılırken bu bilgilere göre kullanıcının bazı işlemlere müsaade edilmesi yönündedir.
Üç çeşit claim türü vardır. Bunlar; registered, public ve private claim’lerdir.
Registered claims: JWT’de önceden rezerve edilmiş claim türleri bulunmaktadır. Bu claimlerin kullanımı zorunlu değildir ancak kullanıldığında yararlı olabilecek claim türleridir. Bu claimlere örnek olarak iss (issuer) exp (expiration time), sub (subject), aud (audience) gibi claimler verilebilir. Diğerlerine IETF Registered Claims sayfasından ulaşabilirsiniz.
Public claims: Registered claimler gibi ancak daha kapsamlı olan önceden kaydedilmiş claimlerdir. Bu listeye IANA JSON Web Token Claims Registry sayfasından ulaşabilirsiniz.
Private claims: Mevcut claimler dışında uygulamanıza özel bilgileri de kullanabilirsiniz.. Örneğin adı ve email adresi gibi claim bilgileri standart kayıtlı claimler iken; kullanıcı id, yaşı, departman adı gibi daha detaylı veri içeren bilgiler private claimlerdir.
Claim’leri de açıkladıktan sonra örnek bir payload verisinin nasıl göründüğüne bakalım;
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Payload dedik ancak isminin fiyakasına aldanmamak gerek 😊 Payload da, header gibi standart bir JSON verisinden fazlası değil. Yine aynı şekilde bu kısım da JWT oluşturulurken header’da olduğu gibi Base64Url ile encode edilecektir.
Bu noktada şunu belirtmek gerekir ki; payload içeriği ile ilgili bir kısıtlama yoktur. Ancak bu veriyi JWT’nin şifrelemediğini bilmek önemli bir konu. Dolayısıyla buraya koyduğumuz herhangi bir bilgi decode edildiğinde herkes tarafından görülebilir. Bu sebeple hassas bir bilgiyi payload içerisine koymamak gerekir.
Dilediğimiz veriyi payload da kullanabiliriz dedik ancak burada JWT’yi amacına uygun kullanmamız gerektiğini de hatırlatalım. JWT içerisindeki payload encode edilerek request ve response’larda kullanılacağı için verinin az olması işlem maliyetini de azaltacaktır.
Signature
Bu kısmın oluşturulabilmesi için Base64Url ile encode edilmiş header, encode edilmiş payload ve secret bilgisine ihtiyaç vardır. Buradaki verilerle ile beraber bir imzalama işlemi yapılarak oluşan çıktı JWT’nin son parçasına eklenir.
Örneğin, bir imza verisi HMAC SHA256 algoritmasını kullanarak aşağıdaki şekilde oluşturulacaktır;
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT’nin geçerli olup olmadığı, Signature (imza) bölümü doğrulanarak yapılır. Buradaki doğrulama işlemi ile JWT içeriğinin göndericiden alıcıya kadarki sürecinde değiştirilmediği, token’ı doğru kişinin gönderdiği anlaşılabilmektedir.
Şimdi gelin JWT’nin nasıl çalıştığını görsel olarak aşağıdaki akış üzerinden inceleyelim.
JSON Web Token (JWT) nasıl çalışır?
- Uygulamaya giriş için kullanıcı adı ve şifre gerektiğinden; ilk adımda client bu bilgileri browser üzerinden HTTP Post ile sunucuya gönderiyor.
- Gönderilen kullanıcı adı ve şifre bilgileri doğrulanıyor. Bilgilerin doğru olması durumunda bir JWT üretim işlemi yapılıyor.
- Üretilen JWT bilgisi, isteği yapan client’a iletiliyor. Bu noktadan sonra tekrar kullanıcı adı ve şifre ile doğrulama yapılmasına gerek kalmayacaktır. Token geçerli olduğu sürece yetkilendirme işlemleri için bu token üzerinden gerçekleşecektir.
- Bir sonraki istek, HTTP üzerinden, JWT’yi Authorization Header bilgisine eklenerek yapılıyor.
- Sunucu, JWT imzasının geçerli olup olmadığını kontrol ederek JWT’nin doğrulamasını yapar.
- Geçerli bir JWT gönderilmişse, Authorization işlemi onaylanarak talep edilen bilgiler client’a gönderilir.
JSON Web Token nasıl kullanılır?
Akış üzerinde de adım adım ilerlediğimiz gibi, kimlik doğrulama aşamasında kullanıcı bilgileriyle oturum açtığında bir JWT üretilerek kullanıcıya iletilir. Buradaki JWT üretim aşamasında token süresinin çok uzun tutulmaması iyi bir pratik olacaktır, aksi halde bir güvenlik zaafiyeti oluşabilir. Kullanıcı belli aralıklarla süresi dolduğunda yeni token talep etmelidir.
Alınan bu token, sonraki isteklerde gönderilmek üzere genellikle client üzerindeki localStorage’larda tutulur. Kullanıcı yetki gerektiren bir kaynağa erişmek istediğinde header içerisinde aşağıdaki şekilde JWT’yi göndermelidir.
Authorization: Bearer <token>
Sunucu client üzerinden gelen bu token’ı doğrulayacak, geçerli ise erişim izni verecektir. JWT içeriğinde tüm gerekli bilgileri bulundurduğu için, daha önce de bahsettiğimiz gibi veri tabanına gitme ihtiyacı azalmış olacaktır.
Bu yazımızda son zamanlarda web uygulamalarında kullanımı sıklıkla artan SON Web Token (JWT) konusunu ele aldık. Token tabanlı doğrulama işlemlerinde geliştiricilere kolaylık sağlayan bu standart ile siz de gelecek projelerinizde yetkilendirme işlemlerinizi kolaylıkla yapabilirsiniz.