JWT(Json Web Token)

Altan Emre Demirci
ucuncubinyil
Published in
6 min readNov 22, 2022

Web uygulamalarında yetkilendirme/kimlik tanımlama işlemi çok önemlidir.

JSON Web Token authorization işleminde kullanabileceğimiz çok güçlü bir standarttır. Çalışma prensibi;

  • Server belirlediğiniz secret‘ı kullanarak bir JSON Web Token oluşturur.
  • Oluşturulan token client’a gönderilir.
  • Client her request gönderdiğinde beraberinde token da gönderir, gönderilen token serverda doğrulanır.

JWT(JSON Web Token) Nedir?

JWT, server ile client arasında dijital olarak imzalanmış dize belirteçleri olarak bilgi iletmek için JSON’u kullanmaya yönelik açık bir standarttır (RFC 7519). HMAC algoritmasıyla veya RSA veya ECDSA kullanılarak bir genel/özel anahtar çifti kullanılarak imzalanabilirler.

Bunu başka bir şekilde söylemek gerekirse: JWT’ler, URL-safe, kompakt ve kendi kendine yeten bir dize olan bir JSON belirtecidir. Tipik olarak, bir kullanıcının doğrulanmış kimliği hakkında bilgi taşırlar. Genellikle kodlanır ve şifrelenir. Web genelinde belirteç uygulamaları için hızla fiili bir standart haline geliyorlar. URL güvenli, tüm özel karakterler basit alphanumeric karakterler olarak kodlandığından belirteç dizesinin bir URL’de kullanılabileceği anlamına gelir. JWT’ler ayrıca opak kabul edilir, çünkü dize kendi başına kod çözme veya şifre çözme olmadan hiçbir bilgi sağlamaz.

Belirteçler genellikle bir yetkilendirme mekanizması olarak düşünülür, ancak authorization kullanıldığı şekilde, bir web uygulaması ile bir sunucu arasında bilgileri güvenli bir şekilde depolamak ve iletmek için bir yol olarak da kullanılabilirler.

JWT ve Cookie arasındaki fark nedir?

Cookie kullanımında client dan gelen request'te göre server session kaydeder, her request’te cookie de yollanır ve server cookie’yi serverda arayarak doğrular.

JWT kullanımında ise client dan gelen request e karşılık server JSON Web Token oluşturur. Sonrasında her request’te token da yollanır ve server tokenın doğruluğunu kontrol eder.

Cookie ile JWT arasındaki fark token kullandığımızda server tarafına herhangi bir bildirimde bulunmamıza gerek kalmamasıdır.

JWT token nasıl oluşturulur?

JWT tokenler nokta (.) ile birbirinden ayrılan 3 bölümden oluşur:

  • Header (Hash algoritmasının belirlendiği bölümdür.)
  • Payload (Verimizi eklediğimiz bölümdür. Burada iss exp gibi bazı keyler rezerve edilmiştir. Örneğin iss keyi token için expiration date belirlememizi sağlar. )
  • Signature (Header, Payload ve secret belirlenen algoritma ile kodlanarak signature elde edilir.)

JWT tokenleri oluşturmak ve doğrulamak için kullandığınız dil ve environment için bir library kullanabilirsiniz. jwt.io adresinden seçeneklere göz atabilirsiniz.

Örneğin Node.js için jsonwebtoken paketini kuralım:

npm install jsonwebtoken

Projemize import edelim.

import jwt from "jsonwebtoken";

JWT Token oluşturmak için:

// jwt.sign(PAYLOAD, SECRET, OPTIONS);
const token = jwt.sign({ username: "Altan" }, "secretdegeri", {
expiresIn: "1d",
});

JWT Tokeni doğrulamak için:

const result = jwt.verify(token, "secretdegeri");

JWT(JSON Web Token) Yapısı

Header(Başlık)

İlgili taraflar arasında karşılıklı anlaşma olduğu sürece, başlıkta sahip olabilecekleriniz konusunda herhangi bir sınırlama olmamasına rağmen. Ancak genellikle başlık iki bölümden oluşur.

type: belirtecin türünü temsil eder ve bu JWT olacaktır
alg: HMAC, RSA, SHA gibi bu belirteci imzalamak için kullanılan algoritmayı belirtir.

Header’ı açarsak şöyle bir şey görürüz.

{
"typ": "JWT",
"alg": "HS256"
}

Sunucu ayarlarında şöyle yaparız.

JWT_ALGORITHM = "HS256"

Payload(Veri)

Claim ve zaman damgası (timesptamp) bilgisini taşır.

İki tür JWT vardır:

JWS: Yük “düz metin” biçimindedir ve içeriğini onaylamak için bir imzası vardır.
JWE: Yük tamamen şifrelenmiştir.
Bunların biraz farklı kullanım durumları vardır. Tek yapmanız gereken, JWT’de depolanan verilerin doğru olduğunu ve kurcalanmadığını doğrulamaksa, o zaman bir JWS uygundur (düzgün bir şekilde uyguladığınızı ve tüm isteklerde imzayı doğruladığınızı varsayarsak). Bu nedenle, bakiyeyi bir JWS’de saklayabilir ve daha sonra bildirilen bakiyenin başlangıçta sakladığınız bakiye olduğunu onaylayabilirsiniz.

Ayrıca verileri gizli tutmak istiyorsanız, bir JWE kullanabilirsiniz. Şifreleme ayrıca verilerin değiştirilmemesini de garanti eder (yine, JWE’yi doğru şekilde uyguladığınızı varsayarsak). Normalde JWT’ye erişimi olan tek kişinin son kullanıcı olduğunu unutmayın, bu nedenle JWT’yi onlardan gizli tutmaktan bahsediyoruz.

Örnek

Hesap bakiyesini payload içinde tutmak isteyelim. Bu yanlış bir karar.

Bir JWT güncellenmeden başka bir işlem yapıldıysa veya eski bir JWT sunulduysa (diğer bir deyişle yeniden oynatma saldırısı), o zaman yanlış bakiyeye sahip geçerli bir JWT’ye sahip olabilirsiniz. Bu, aktif saldırganlar olmadan bile çok muhtemeldir. 1'den fazla uygulama kullanan bir kullanıcıyı düşünün. Varsayımsal senaryonuzda, bir cihazda bir JWT’de bir bakiye depolanırsa ve ardından kullanıcı başka bir cihazda oturum açıp bir işlem yaparsa ne olur? JWT’nin kendisi geçerli olmasına ve süresi dolmamış olmasına rağmen, ilk cihaz için JWT’deki veriler artık yanlış. Bu, geçerli ancak yanlış JWT’lerin meydana gelebileceği birçok yoldan yalnızca biridir.

Örnek
Payload’u açarsak şöyle bir şey görürüz.

{
"iss": "http://trustyapp.com/",
"exp": 1300819380,
"sub": "users/8983462",
"scope": "self api/buy"
}

Signature
Algoritma olarak HMAC-SHA256 ve none kullanılabilir. JWT’nin değiştirilmediğini garanti eder. JWT’yi şifrelemez.

İşlem sonucunda elimize nokta karakteri ile ayrılmış şu string geçer.

token= encodeBase64(header)+ ‘.’ +encodeBase64(payload)+ ‘.’+encodeBase64(signature)

HMACSHA256( 
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

Sunucu Token’ı İmzalar

Örneğin, bir sunucu “yönetici olarak oturum açmış” iddiasına sahip bir belirteç oluşturabilir ve bunu bir müşteriye sağlayabilir. İstemci daha sonra yönetici olarak oturum açtıklarını kanıtlamak için bu belirteci kullanabilir. Tokenlar, sunucunun anahtarı tarafından imzalanır, böylece sunucu, tokunun meşru olduğunu doğrulayabilir.

Bu imzanın gizlilik sağlamadığını anlamak çok önemlidir. Bu bilgiler herkes tarafından görülebilir. İmza, tokenın değiştirilmediğini garanti eder, ancak verileri gizlemez (küçük bir çocuk amcasının iPhone 4'ünde Base64 kodunu çözebilir). Hassas bilgiler göndermek istiyorsanız bir JWT şifrelenmelidir.

İmza İçin HMAC Kullanılırsa
Bir mesaj authentication koduyla (örneğin, HMAC-SHA256) imzalanır (algoritma, JWT’nin başlığında belirtilir).

Claim Nedir
Talepler, tipik olarak bir kullanıcı olan varlık ve herhangi bir ek veri hakkındaki ifadelerdir. Üç tür iddia vardır:

- Registered claims: RFC 7519 spesifikasyonunda tanımlanan bir dizi önerilen talep. Bazı örnekler iss, exp ve aud’dur.

- Public claims: Token kullanıcıları tarafından tanımlanabilen, ancak çarpışmayı önlemek için adlandırma kurallarına uyması gereken kullanıcı tanımlı iddialar (IANA JSON Web Belirteci Kayıt Defterinde tanımlanmalı veya çarpışmaya dayanıklı bir ad alanı içeren bir URL olarak tanımlanmalıdır) çünkü bunlar genel ad alanındadır.

-Private claims: Üzerinde anlaşmaya varan taraflar arasında bilgi paylaşmak için kullanılan isteğe bağlı özel iddialar (ve özel oldukları için ad çakışması konusunda endişelenmenize gerek yoktur).
Talep için zaman damgası olabilir. Açıklama şöyle.
iddiaları içeren bir yüke sahip olmak (bir zaman damgası ile donatılmış)

Registered Claim
IANA “JSON Web Token Claims” kaydında kayıtlı olan iddialar var. Bu iddiaların her durumda kullanılması veya uygulanması zorunlu değildir; bunun yerine, bir dizi faydalı, birlikte çalışabilir iddia için bir başlangıç ​​noktası sağlamak üzere kayıtlıdırlar.

iss, belirteci veren kişidir. Bu kayıtlı bir iddiadır.
exp, jetonun süresinin dolduğu zamandır. Ayrıca kayıtlı bir iddia.
sub, Bu genellikle bir kullanıcı tanımlayıcısıdır. Ayrıca kayıtlı bir iddia.
scope, OAuth 2.0 ile yaygın olarak kullanılan özel, özel bir taleptir.

1. iss (issuer): “iss” (veren) talebi, JWT’yi yayınlayan sorumluyu tanımlar. Bu talebin işlenmesi genellikle uygulamaya özeldir. “iss” değeri, bir Dize veya URI değeri içeren büyük/küçük harfe duyarlı bir dizedir. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

2. sub (subject): Bu iddia, JWT’nin konusunu (kullanıcı) temsil etmektedir. Konu değeri, yayınlayan bağlamında yerel olarak benzersiz olacak şekilde kapsamlandırılmalı veya küresel olarak benzersiz olmalıdır ZORUNLU. Bu talebin işlenmesi genellikle uygulamaya özeldir. “alt” değer, bir Dize veya URI değeri içeren büyük/küçük harfe duyarlı bir dizedir. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

3. aud (audience): Bu iddia, JWT’nin amaçlanan alıcısını temsil eder. Talebi işleyen taraf, bu talep mevcut olduğunda kendisini “aud” talebindeki bir değerle tanımlamıyorsa, JWT’nin reddedilmesi ZORUNLUDUR. Genel durumda, “aud” değeri, her biri bir Dize veya URI değeri içeren, büyük/küçük harfe duyarlı dizelerden oluşan bir dizidir. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

4. exp (expiration): “Son kullanma süresi” (son kullanma süresi) iddiası, JWT’nin işlenmek üzere KABUL EDİLMESİ GEREKEN veya sonrasında sona erme süresini tanımlar. “Exp” talebinin işlenmesi, geçerli tarih/saatin “exp” talebinde belirtilen son kullanma tarihinden/saatinden önce OLMALIDIR. Genellikle değer, tercihen saniye cinsinden kısa tutulur. Değeri, NumericDate değeri içeren bir sayı OLMALIDIR. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

5. nbf (not before): “nbf” (önce değil) iddiası, JWT’nin işleme için KABUL EDİLMEMESİ GEREKEN zamanı tanımlar. “nbf” talebinin işlenmesi, geçerli tarih/saatin “nbf” talebinde listelenen daha önce olmayan tarih/saatten sonra veya bu tarih/saatten sonra OLMALIDIR. Uygulayıcılar, saat kaymasını hesaba katmak için genellikle birkaç dakikayı geçmeyecek şekilde küçük bir hareket alanı SAĞLAYABİLİRLER. Değeri, NumericDate değeri içeren bir sayı OLMALIDIR. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

6. iat (issued at): “iat” (yayınlanma yeri) iddiası, JWT’nin düzenlendiği zamanı tanımlar. Bu iddia, JWT’nin yaşını belirlemek için kullanılabilir. Değeri, NumericDate değeri içeren bir sayı OLMALIDIR. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

7. jti (JWT ID): “jti” (JWT Kimliği) iddiası, JWT için benzersiz bir tanımlayıcı sağlar. Tanımlayıcı değer, aynı değerin yanlışlıkla farklı bir veri nesnesine atanma olasılığının ihmal edilebilir olmasını sağlayacak şekilde atanmalıdır ZORUNLU; uygulama birden fazla veren kullanıyorsa, farklı verenler tarafından üretilen değerler arasında da çarpışmalar önlenmelidir ZORUNLU. “jti” iddiası, JWT’nin yeniden oynatılmasını önlemek için kullanılabilir. “jti” değeri, büyük/küçük harfe duyarlı bir dizedir. Bu talebin kullanımı İSTEĞE BAĞLIDIR.

--

--