JSON Web Token(JWT) Standardı
Önceki yazımızda JSON API Standardı üzerine değinmiştik. Bu yazımızda da kimliklendirme işlemleri için JSON Web Token Standardı’nın kullanımı üzerine değineceğiz. Sizin de bildiğiniz gibi her bir projede kullanıcı kimliklendirilmesi işlemlerinde vazgeçilmez unsurlardan biri token yapısıdır. Genel senaryo şudur:
- İstemci kullanıcı adı ve parola ile birlikte sunucuya login isteği gönderir.
- Sunucu bu bilgileri alarak veri tabanından sorgulama yapar ve kullanıcı adı ile kendi gizli anahtarını birleştirip bir özet fonksiyonundan geçirir. Fonksiyon sonucu token döner ve sunucu bu bilgiyi veri tabanında ilgili kullanıcının TOKEN kolonuna yazar.
- Sunucu token’ı istemciye iletir.
- İstemci bundan sonraki her işlemde bu token’ı kullanarak gönderim gerçekleşir ve sunucu tarafında her defasında veri tabanından token’ın geçerli olup olmadığını kontrol edilir.
İstemci her defasında ad/parola ikilisini sunucuya göndermek zorunda kalmadığı gibi kendi tarafında parola bilgisinin tutulması yerine sunucuda oluşturulan token bilgisini tutmasıyla daha güvenli bir yapı oluşturulmuş olur. Fakat burada 2 farklı konu karşımıza çıkıyor:
- Token her sunucu işlemi için veri tabanından kontrol ediliyor. 1 birimlik işiniz varsa 2 birimlik iş yapmış oluyorsunuz.
- Standart bir yapı/algoritma olmadığı için oluşturulacak token güvenliği/implementasyonu ayrı bir tartışma konusu haline geliyor.
Bu sorunları aşmanın yollarından biri de bu yazının konusu olan JSON Web Token (JWT)
kullanmaktan geçiyor.
JSON Web Token nedir?
JSON Web Token (JWT), iletişim yapan birimler arasındaki veri alışverişinin güvenli bir şekilde sağlanması için bir JSON nesnesi (token) kullanarak daha kompakt ve bilginin kendini kendini betimlediği bir yol sunan endüstri standardıdır (RFC 7519). Oluşturulan token, dijital olarak imzalandığı için doğrulanabilir ve güvenilirdir. Bir JWT, HMAC algoritması ve gizli bir kelime kullanılarak imzalanabilir. İmzalama sürecinde HMAC yerine RSA algoritmasından yararlanılarak açık ve gizli anahtar ikililerinin kullanılması da sağlanabilir. JWT’nin özelliklerine biraz daha değinelim:
- Kompakttır: Boyutunun küçük olması sayesinde URL üzerinden gönderilebilir, POST parametresi olarak eklenebilir veya HTTP başlığı içerisinde yer alabilir. Kompakt olmasının diğer bir avantajı ise aktarımın hızlı gerçekleşmesidir.
- Kendi-kendini betimler: Token içerisinde isteği yapan kullanıcı ile ilgili gerekli bütün bilgi mevcuttur. Bu sayede kimliklendirme için veri tabanında birden fazla sorgu yapılması engellenmiş olur. Daha fazla detaylı bilgi için JWT Handbook‘a bakabilirsiniz.
Ne zaman JWT kullanmalısınız?
Aşağıdaki kısımda JSON Web Token’ın faydalı olduğu senaryolar yer almaktadır:
- Kimliklendirme: Aslında en temel kullanım senaryosu budur. Kullanıcının başarılı yaptığı giriş işlemi sonrasında gerçekleştireceği her istek JWT’yi içerir. Bu sayede kullanıcının hangi kaynaklara/web sayfalarına erişeceği bu token bilgisi ile kontrol edilir. Farklı domain’ler arasında kolayca token değiş-tokuşunu sağladığı için, tek seferlik giriş (single sign on) senaryolarında yoğun olarak kullanılmaktadır.
- Bilgi değiş-tokuşu: JWT’ler dijital olarak imzalanabildiği için bilginin iletişim yapan birimler arası güvenli bir şekilde gerçekleşebilmesi için iyi bir yöntem sunar. Örneğin açık/gizli anahtar ikilileri kullanıldığında bilgiyi gönderen kişinin gerçekte kim olduğunu söylemek mümkündür. Buna ek olarak, JWT’deki header ve payload kısımları dahil edilerek oluşturulan imza sayesinde gelen bilginin değiştirilip/değiştirilmediği kolayca doğrulanabilir.
JWT’nin yapısı
JWT’ler birbirine nokta (.
) ile bağlanan 3 kısımdan oluşur:
- Hedaer (Başlık)
- Payload (Yük)
- Signature (İmza)
Böylece tipik bir JWT aşağıdaki gibi görünür:
xxxxx.yyyyy.zzzzz
Haydi bahsettiğimiz kısımlara değinelim.
Header (Başlık)
Başlık genellikle 2 parçadan oluşur:
- typ: Token’ın türünü belirler. “JWT” değerine sahiptir.
- alg: Kullanılan özet (hash) algoritmasını gösterir. HMAC SHA256 veya RSA gibi değerler alabilir. Örnek bir header aşağıdaki şekildedir:
{
"alg": "HS256",
"typ": "JWT"
}
Daha sonra bu JSON bilgisi Base64Url ile kodlanarak JWT’nin ilk parçasını oluşturur.
Payload (Yük)
Token’ın ikinci parçası olan payload, ilgili claim
‘leri içerir. Claim’ler kullanıcı hakkında bilgiler sunan ifadelerdir. Ayrıca metadata bilgisi de içerebilir. reserved
, public
ve private
olmak üzere 3 tip claim bulunmaktadır:
- Reserved (Ayrılmış) claim’ler: Önceden tanımlanmış claim’lerdir. Kullanılması zorunlu değildir fakat önerilir. Yararlıdırlar ve birlikte çalışabilen bir claim kümesinin oluşturulmasını sağlarlar. Bunlardan bazıları: iss (issuer) (yayınlayıcı), exp(expiration time) (son kullanım zamanı), sub (subject) (konu), aud (audience) (hedef kitle) ve diğerleridir. Not: Farkettiğiniz gibi kompakt olması açısından claim isimleri yalnızca 3 karakter uzunluğundadır.
- Public (Açık) claim’ler: İsteğe göre eklenen alanlardır. Fakat rezerve edilmiş IANA JSON Web Token kayıtları veya URI’da tanımlanan parametreler ile kullanımın çakışmasından kaçınılmalıdır.
- Private (Gizli) claim’ler: Bilgi paylaşımı için tarafların kendi aralarında anlaştığı özel claim’lerdir.
Üstteki 3 claim bilgisine dayanarak örnek bir payload aşağıdaki şekilde oluşturulabilir:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Daha sonra bu JSON bilgisi Base64 ile kodlanarak JWT’nin ikinci parçasını oluşturur.
Signature (İmza)
Signature kısmının oluşturulabilmesi için base64 ile kodlanmış header, base64 ile kodlanmış payload, gizli bir kelime (secret) ve header’da tanımlanan algoritma gereklidir.
Örneğin HMAC SHA256 algoritması kullanılarak aşağıdaki şekilde imza oluşturulabilir:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Oluşturulan imza, JWT’yi gönderenin kim olduğunu belirtir ve iletim yapılan bilginin göndericiden alıcıya gelene kadar değişip değişmediğinin kontrolünde kullanılır.
Şimdi öğrendiklerimizi bir araya getirelim
Base64 string ifadelerinin nokta ile birleştirilmesiyle oluşan JWT, SAML gibi XML-temelli daha karmaşık standartların aksine HTML ve HTTP ortamlarında kolayca üretilebilir.
Önceki header ve payload bilgisinin encode edilmiş hali ve secret kullanılarak imzalanmış yapıdan oluşan bir JWT aşağıdaki şekilde gösterilmektedir:
JWT ile denemeler yapmak için jwt.io‘yu ziyaret edebilir ve bu konseptleri pratiğe dökebilirsiniz. jwt.io üzerinden JWT oluşturabilir, çözümleyebilir, doğrulayabilirsiniz.
JWT nasıl çalışıyor?
Kimliklendirme işlemlerinde, kullanıcı kendi kimlik bilgileriyle başarılı bir şekilde giriş yaptığında, geleneksel bir yaklaşım olan sunucu tarafında session açılıp kulanıcıya cookie dönülmesi yerine, geriye bir JWT döndürülür ve tekrar kullanılmak üzere localStorage veya cookies gibi yapılarda JWT saklanır.
Kullanıcı korunmuş bir kaynağa erişmek istediğinde, istemci tarafından Authorization başlığı içerisinde Bearer şeması kullanılarak JWT sunucuya iletilmelidir. Oluşturulan HTTP başlığı içeriği aşağıdaki gibi olmalıdır:
Authorization: Bearer <token>
Buradaki stateless (durumsuz) kimliklendirme mekanizması sayesinde session’da yapılanın aksine kullanıcının durum bilgisi asla sunucunun hafızasında (RAM’inde) saklanmamış olur. Sunucudaki korunan kaynağa erişim izni Authorization başlığındaki JWT’nin geçerliliği ile kontrol edilir. Eğer geçerli ise, kullanıcının korunan kaynağa erişim izni sağlananır. JWT’ler kendi kendini betimledikleri için, bütün gerekli bilgi JWT’nin içerisindedir. Bu sayede veritabanı üzerinden kimlik doğrulama için çoklu sorgu işlemleri yapılmasının önüne geçilmiş olur.
Aşağıdaki diyagramda JWT’nin işleyişi yer almaktadır:
Neden JWT kullanmalısınız?
Simple Web Tokens (SWT) ve Security Assertion Markup Language Tokens (SAML) ile kıyasla JSON Web Tokens (JWT)‘ın neden daha iyi olduğuna değinelim.
JSON içeriğinin XML’e göre daha yalın olması sebebiyle, base64 ile kodlandığında daha küçük bir hale gelen JWT, SAML’den daha kompakt olmaktadır. Bu sayede, HTML ve HTTP ortamlarında JWT kullanımı daha iyi bir seçim haline gelmektedir.
SWT, HMAC algoritması kullanılarak ortak bir gizli anahtar ile sadece simetrik olarak şifrelemeye izin vermektedir. Oysa ki, JWT ve SAML standartları imzalama için X.509 sertifikasını oluşturacak şekilde açık/gizli anahtar ikililerini kullanabilirler. Fakat SAML’da arkanızda güvenlik açığı bırakmayacak şekilde XML imzalama işlemi JSON imzalamaya göre çok daha zor gerçekleştirilir.
JSON parser’lar, direkt olarak nesnelere dönüşüm işlemini gerçekleştirebildiği için birçok programlama dilinde yaygın olarak kullanılıyor. XML cephesinde ise doğal yollarla bir XML dokümanının nesneye dönüştürülmesi için bir yöntem bulunmamakta. Bu nedenle JWT ile çalışmak, SAML ile çalışmaya göre çok daha kolaylık sağlıyor.
Kullanımı baz alacak olursak, JWT bütün bir internet ölçeğinde kullanılmaktadır. Üstte bahsedilen konular da, başta mobil olmak üzere internete bağlı birçok platforma yönelik istemci taraflı JWT token’larının işlenme sürecinde kolaylıklarını ele almaktadır.
Bu yazımızda JWT ile kimliklendirme işlemlerinden bahsettik. Eğer sizin de bu konuda istek ve görüşleriniz varsa yorum yazabilir, fikirlerinizi bizimle paylaşabilirsiniz.
14 Comments
Abdullah Çetinkaya
8 Kasım 2017 at 10:38İhtiyaç vardı ama cözümünü bilmiyordum kendimce birşeyler üretmiştim. Böyle birşey kaliteyi biraz daha ileri atıyor. Teşekkürler.
Zafer Ayan
14 Kasım 2017 at 22:19Rica ederim. Özel bir token yapısı oluşturmaktansa bu şekilde iyi test edilmiş ve standart yapıları kullanmak daha iyi sonuç verecektir. .NET’te JWT’yi kodlamak için bu nuget paketini inceleyebilirsiniz: https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/
ahmet
18 Kasım 2017 at 12:28Peki biz jwt kullanarak tek bir api uzerinden hem webe hemde mobilde kullansak bunun ne gibi bi artisi olabilir. Veya jwtnin baska bi alternatifi varmidir
Zafer Ayan
20 Kasım 2017 at 21:53JWT’yi servis olarak dışa açıp hem mobil hem de web’de tabi ki kullanabilirsiniz. Bu sayede kimliklendirme işlemlerini sadece tek bir servis üzerinden gerçekleştirebilirsiniz. Yeni projeler için tekrar tekrar servis yazmanız gerekmez. JWT alternatifleri üstte de belirttiğim gibi eski bir XML alternatifi olan SAML. SAML-P, WS-Trust ve WS-Federation gibi protokollerde ve SOAP servislerinde kullanılıyor. SAML’in JWT’ye göre biraz daha karmaşık bir yapısı var.
Kemal
24 Kasım 2017 at 12:21Merhaba,
JWT ile OAuth2 arasında ne tür farklar vardır?
Ayrıca bir karşılaştırma makalesi paylaşabilir misiniz?
Zafer Ayan
24 Kasım 2017 at 23:27JWT nihayetinde bir token sadece. OAuth’u ise kimlinlendirme/yetkilendirme yapabileceğiniz bir framework gibi düşünebilirsiniz. OAuth, token aktarımı için JWT’yi kullanabilir. Tavsiyem, eğer Facebook’un “Facebook ile giriş” mekanizmasını oluşturduğu gibi kendi kimliklendirme mekanizmanızı oluşturmak gayesindeyseniz OAuth’u tercih etmeniz. Fakat kullanıcılarınız sadece kendi sunucunuz üzerinde işlemler yapacaksa JWT gibi bir lightweight mekanizma işinizi görecektir.
Karşılaştırma için aşağıdaki makaleyi inceleyebilirsiniz:
https://spin.atomicobject.com/2016/05/30/openid-oauth-saml/
Not: OpenID’nin, OAuth’un JWT’li versiyonu gibi düşünebilirsiniz.
Teşekkürler,
ahmet
1 Aralık 2017 at 22:21Öncelikle makale için teşekkürler . Takıldığım bir kısım var kullanıcı yetkilerini token içerisinde gönderdiğimizi varsayalım expires 30 dakika diyelim. 30 dakika dolmadan kullanıcı yetkisini değiştirirsem ilk request de neolur ? tekrar bir token mi alır yoksa eski tokendeki yetkileri ile devam mı eder ?
Zafer Ayan
2 Aralık 2017 at 03:09Güzel yorumun için çok teşekkür ederim.
Kullanıcı yetkisi değiştirildiğinde, sunucu tarafında farklı bir token oluşacağı için, istemcinin gönderdiği ve sunucunun beklediği token birbiriyle uyuşmaz ve sunucu burada 401: Unauthorized HTTP durum kodunu geri döndürür. Sen de belirlediğin durumu test edebilmek için buradaki sayfayı ziyaret edebilirsin: https://jwt.io/#debugger-io
Teşekkürler,
Ahmet
3 Aralık 2017 at 12:48Anladım teşekkür ederim.
Selçuk İTMİŞ
15 Aralık 2017 at 08:32Merhaba,
JWT endüstri standardı oldu artık. Ben de projelerimde kullanıyorum gayet memnunum.
Arkadaş da çok açıklayıcı şekilde anlatmış, teşekkür ediyoruz. Oturum ile ilgili işlemlerinizde JWT kullanmanızı şiddetle tavsiye ederim.
Zafer Ayan
20 Aralık 2017 at 23:40Selçuk Bey değerli yorumunuz ve önerileriniz için teşekkür ederim.
İyi çalışmalar dilerim.
Samet
11 Şubat 2018 at 10:00Merhaba, kafama takılan bir yer; klâsik cookie based sessiona karşı avantaji nedir, hangi alanlarda hangisini tercih etmemiz daha iyi olur.
Ayrıca bu güzel paylaşımınız için çok teşekkür ederim.
uco
14 Ekim 2018 at 21:14Yazida da bahsedildigi gibi server side bir state kaydedilmeye gerek yoktur. Cookie storage saldiriya acik mekananizmadir.
Hangi alanlar? -> Ozellikle auth ticket, credentials disinda birseyleri de beraberinde tasimak istediginizde, ki bu role olabilir, ya da app specific bir degisken/identifier olabilir, JWT en dogru tercih olur.
Zafer Ayan
21 Ekim 2018 at 03:09uco güzel açıklamış. Güvenlik haricinde JWT’nin en güzel yanı bence basitliği ve iş bitiriciliği.
Cookie based authentication ASP MVC uygulamalarında kullanmak doğru olacaktır. Zira ASP MVC’de cookie ile bu işi yapmak oldukça kolay ve güvenlik mekanizmaları da gayet başarılı. REST servis tarafında ise JWT kullanmak daha iyi sonuçlar verecektir.
Teşekkürler,