Asp.Net Core API — JWT
Sunucu tarafında gizli bir anahtar ile (mesela “ben sevdim eller aldı”), sessionId bilgisini üretir, cookie içinde bu bilgiyi kullanıcıya verir. Bundan sonra kullanıcının her talebinde cookie de sunucuya gönderilir ve içinde sessionId bilgisi de sunucuya taleple birlikte ulaşır. Sunucu sessionId bilgisiyle, tüm oturumları(session) tuttuğu yere bakarak gelen kullanıcının kim olduğunu çözümler. Eğer sessionId ile ilintili bir kullanıcı yoksa, kullanıcıyı giriş sayfasına yönlendirir.
Yukarıdaki paragrafta sessionId yerine token kelimesini koyarak okuyunca aynı işin %5 farklısını gerçekleştirdiğimizi düşünerek öğrenmeye devam edebilirsiniz.
Gelelim %5'e Farklılığa
❤ Cookie içinde saklanmadığı için ele geçirilme ihtimali yok. LocalStorage üstünde saklanarak her talepte gönderildiği için tekrar kullanılabilir.
❤ Token bilgisini sunucuda saklama gereği yok, çünkü gizli anahtar sunucuda mevcut ve header üstünde gelen token bilgisi için “token geçerli mi” kontrolü yapabiliriz.
❤ Her talepte oturumu bulmak için sunucu tarafında arama yapılmaz, tokenı doğrulamak ve içeriğini ayrıştırmak için sadece HMAC SHA-256'yı hesaplamanız gerekir.
❤ SessionId tek bir bilgi iken token içinde daha fazla bilgi gönderebiliriz.
Bu bilgilere claim(iddia, hak) diyoruz ve JWT nin RFC 7519 standartında 3 tip claim’den bahsediliyor(Registered, Public ve Private claim adları).
Kayıtlı (registered) Claim Adları
- Issued At (iat) — Token’ın yaratıldığı tarih
- Not Before (nbf) — Token’ın geçerli olacağı başlangıç tarihi
- Expires (exp) — Token’ın geçersiz olacağı tarih
Mesela yukarıdaki 3 claim ile şunu yapabilirsiniz:
"iat": 123456, // şimdi token'ı oluşturduk
"nbf": 15678, // yarın saat 15:00 ten önce işe yaramasın bu token
"exp": 17989, // ertesi gün 22:00'de kullanılamasın, geçersiz olsun
- Issuer (iss) — Token’ı oluşturan kişi/kurum
- Audience (aud) — Token kimin için yaratıldı (kim bu tokenı kullanacak)
- JWT ID (jti) — JWT için benzersiz tanımlayıcı. JWT’nin tekrar kullanılmasını önlemek için kullanılabilir. Tek kullanımlık bir token için bu claim kullanılabilir.
{
"iss": "Şirket Adı veya adresi olabilir",
"exp": 1527320912,
"kendi_claim_adim": "metin olsun değeri",
"mottomuz": "anne yazılımı kadar lezzetli",
"alGoturIndirimi": true,
"iskonto": 12
}
Bir token 2 nokta ile ayrılmış 3 bölümden oluşuyor.
- Header (Başlık)
- Payload (Yük)
- Verify Signature (doğrulama imzası)
https://jwt.io/ Adresinde görsel olarak anlaşılsın diye 3 renk ile gösteriliyor. Her bölüm base64
ile kodlanmış bir metindir. Her bölümü kopyalayıp https://www.base64decode.org/ adresinde metin olarak encode edebilir ve içeriğini okuyabilirsiniz.
Kırmızı olan HEADER (başlık) bölümüdür. Token’ın hangi alogritmayla imzalandığını ve tipini gösterir. Aşağıdaki örnekte (genelde de bu kullanılır) HMAC-SHA256 simetrik güvenlik anahtarı kullanılmış. Yani bir gizli anahtar ile metin imzalanacak demektir. Asimetrik olsaydı genel ve gizli iki anahtar kullanılacaktı.
Gizli anahtar sadece sunucu tarafından biliniyor. 2. Bölüm olan PAYLOAD (yük) kısmındaki bilgileri algoritmada belirtilen yöntem ve sunucudaki gizli anahtarla imzalandıktan sonra oluşan imzayı açık maviyle gösterilen 3. bölümde yani VERIFY SIGNATURE (doğrulama imzası) kısmında tutar.
İlk 2 bölümdeki bilgiler(header ve payload) istemci tarafında base64 decode işlemine tabi tutularak içeriği çözümlenir. Bu yüzden sakın sunucuda ve gizli kalması gereken anahtarı claim olarak token içine yazmayın. Sunucudan gönderilecek bilgilerin imzası oluşturulup tokenın 3. bölümüne yazıldıktan sonra, kullanıcı payload kısmını değiştirse bile gizli anahtarı bilmeyeceği için sunucu tarafında geçerli bir imza oluşturamayacak.
metin = base64UrlEncode(header) + "." + base64UrlEncode(payload);
imza = HMACSHA256(metin, 'gizli_anahtar_cok_kisa_ve_uzun_olmamali');token = metin + "." + imza
KODLAYALIM
AuthController üstünde basitçe token hazırlamanın yolunu göreceksiniz. Zaten login olmak isteyen kullanıcı bir token sahibi olduktan sonra artık aldığı token ile isteklerini yapacak.
Startup.cs
Dosyasında asp.net core web api uygulamasında token kontrolü nasıl yapılıyor, swagger için yapılacak ayarlamaları açıklamalarıyla anlattım.