Günümüzde web güvenliği, kullanıcı kimlik doğrulama ve yetkilendirme konularında en çok tercih edilen çözümlerden biri JSON Web Tokens(JWT) teknolojisidir. JWT, web uygulamaları ve API'ler arasında güvenli veri iletimi sağlayan kompakt ve kendi kendini doğrulayan bir token standartıdır. Bu yazıda, JWT'nin ne olduğunu, nasıl çalıştığını ve avantajlarını detaylı bir şekilde ele alacağız.
JWT(Json Web Tokens)Nedir:
JSON Web Token(JWT),
JSON formatında veri taşıyan
bir token türüdür.
JWT, genellikle kullanıcı
kimlik doğrulaması ve yetkilendirmesi için kullanılır. Token, üç ana bölümden oluşur :
Header(Başlık) : Token'ın türünü (genellikle "JWT") ve kullanılan imzalama algoritmasını belirtir.
Payload(Yük) : Kullanıcı bilgileri ve diğer verileri içeren bölüm. Bu
bilgiler "claims" olarak adlandırılır ve kullanıcı kimlik bilgileri veya izinler gibi verileri taşıyabilir.
Signature(İmza) : Token'ın bütünlüğünü korumak ve yetkisiz değişiklikleri önlemek için kullanılan şifreli imzadır.
JWT'nin Avantajları :
Taşınabilirlik : JWT'ler, URL, parametreler, HTTP başlıkları veya hatta cookie'ler içinde taşınabilir.
Kendi Kendini Doğrulayan : Token, imza ile korunduğundan, token'ın değiştirilmediğinden emin olunur.
Performans : JWT'ler, sunucu tarafında oturum bilgilerini saklamadan, istemci tarafında saklanabilir. Bu, sunucu üzerindeki yükü azaltır.
Esneklik: JWT'ler, farklı programlama dilleri ve platformlarda kullanılabilir.
Encoded kısmında gördüğümüz gibi kompakt ve şifrelenmiş yapıda olan token; Decoded kısmında ise bu token'ın çözümlenmiş hali bulunmakta.
Header (Başlık) :
"alg" : Kullanılan özet (hash) algoritmasını gösterir. HMAC SHA256 veya RSA gibi değerler alabilir.
"typ" : Token’ın türünü belirler. “JWT” değerine sahiptir.
Payload (Yük) :
Bu kısma Claim dataları belirtilir. Bu kısımdaki veriler istemci ve sunucu arasında paylaşılır ve eşsiz olmalıdır.
'Claim' : Doğrulanmış kullanıcının istemci ve sunucu arasında paylaşılmak istenen bilgileri tutar. Payload içerisinde hassas bilgiler olmamalıdır. Ortak ve decode edildiğinde işe yaramayacak veriler belirtilmelidir. Ad, Soyad, Id, Mail vs..
Signature (İmza) :
JWT Token bilgisinin son kısmıdır. Bu kısmın oluşturulması için header, payload ve gizli anahtar gereklidir. İmza ile veri bütünlüğü garanti altına alınmış olur.
Peki bu 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.
JWT Oluşturulması, Kullanımı, Authentication ve Authorization İşlemleri
İlk olarak Token adında bir klasör oluşturup içerisine TokenRequestModel ve CreateToken adında iki ayrı sınıf oluşturuyoruz.
TokenRequestModel, Claimlenecek bilgilerin bulunduğu sınıftır. Sizin Model yapınız farklı olabilir. Claimlenecek bilgilerinize göre bu sınıfı kendinize göre uyarlayabilirsiniz.
Bu işlemleri yaptıktan sonra CreateToken sınıfımızı yazabiliriz.
İlk olarak IConfiguration Interface'nden 'Dependency Injection' ile _configuration objemizi oluşturarak başlıyoruz. Dependency Injection ile alakalı daha detaylı bilgiye sahip olmak isterseniz buraya tıklayarak ilgili yazımı okuyabilirsiniz.
CreateTokenHandler adında bir method oluşturup az önce oluşturduğumuz TokenRequestModel'i parametre olarak veriyoruz. Claim türünde bir liste oluşturup token içerisine Claimlemek istediğimiz dataları bu şekilde veriyoruz.
Daha sonra,
SymmetricSecurityKey : Bu kısımda bir SymmetricSecurityKey oluşturulur. Bu anahtar, token'ın imzalanmasında kullanılacak olan simetrik şifreleme anahtarıdır. Bu anahtar, AppSettings:Token bölümünden alınan bir değerle oluşturulur.
SigningCredentials : Token'ı imzalamak için gerekli olan kimlik bilgilerini oluşturur. Bu kimlik bilgileri, daha önce oluşturulan simetrik anahtar ve HMAC-SHA512 algoritması kullanılarak oluşturulur.
Bu kısımda en önemli nokta "appsettings.json" içerisinde verdiğimiz alanların isimleri ile CreateTokenHandler içerisinde verdiğimiz isimler aynı olmalıdır yoksa bu bilgiler hiçbir şekilde EŞLEŞEMEZ!
appsettings.json içerisine girip AppSettings adında (bir anahtar ya da düğüm de diyebilirsiniz) oluşturuyoruz. Bir önceki görselde bulunan CreateToken sınıfımızda bulunan SymmetricSecurityKey, AppSettings:Token bölümünden alınan bir değerle oluşturuluyor.
UYARI!!
launchSettings.json içerisine girdiğimizde "ASPNETCORE_ENVIRONMENT" : "Development" diye bir kısım göreceğiz. Bu kısım bizim Development ortamında çalıştığımızı göstermektedir. Bu yüzden appsettings.json altında appsettings.Development.json içerisine de yukarıdaki "AppSettings" bilgilerini yerleştirmek zorundayız. Aksi taktirde verdiğimiz token bilgileri eşleşmeyecektir!!
-
- issuer: Token’ı oluşturan yetkiliyi tanımlar. Bu değer,
AppSettings:Issuer
ayarından gelir.
- issuer: Token’ı oluşturan yetkiliyi tanımlar. Bu değer,
-
- audience: Token’ın hedef kitlesini belirler. Bu değer,
AppSettings:Audience
ayarından gelir.
- audience: Token’ın hedef kitlesini belirler. Bu değer,
-
- claims: Yukarıda tanımlanan kullanıcı kimlik bilgilerini (
claims
) token’a ekler.
- claims: Yukarıda tanımlanan kullanıcı kimlik bilgilerini (
-
- expires: Token’ın geçerlilik süresini belirler. Bu örnekte, token 300 dakika (5 saat) sonra geçersiz olur.
-
- signingCredentials: Token’ı imzalamak için kullanılan kimlik bilgilerini belirtir.Son olarak JwtSecurityToken nesnesini bir dizi(‘string’) formatına çevirerek CreateTokenHandler aracılığı ile tokenı döndürüyoruz.
Şimdii gelelim işin Authentication kısmına.
Authentication (Kimlik Doğrulama), bir kullanıcının veya sistemin kim olduğunu doğrulama sürecidir. Başka bir deyişle, bir kullanıcının veya sistemin iddia ettiği kimlik olduğundan emin olmak için kullanılan bir yöntemdir.
Program.cs içerisine gelip Atuhentication için gereken kısımları yazıyoruz.
En baştan başlayacak olursak:
AddAuthentication : Bu metod, ASP.NET Core'da kimlik doğrulama hizmetlerini yapılandırmak için kullanılır.
AuthenticationScheme : JwtBearerDefaults.AuthenticationScheme değeri, "Bearer" olarak belirlenir. Bu, kimlik doğrulama türünün JWT'yi temel aldığını belirtir. Yani, Authorization başlığına eklenen bir "Bearer" token ile doğrulama yapılacağını ifade eder.
AddJwtBearer : Bu metod, JWT Bearer token'larını doğrulamak için gerekli ayarları yapar.
options : AddJwtBearer metoduna iletilen options, JWT doğrulama sürecini yapılandırmak için kullanılır.
TokenValidationParameters : Bu yapı, JWT'nin doğrulanması sırasında kullanılacak olan parametreleri tanımlar.
ValidateIssuer = true : Token'ı oluşturan yetkiliyi (issuer) doğrular. Token'ın kimin tarafından oluşturulduğunu kontrol eder.
ValidateAudience = true : Token'ın hedef kitlesini (audience) doğrular. Token'ın belirli bir alıcı (örneğin, API) için oluşturulup oluşturulmadığını kontrol eder.
ValidateLifetime = true : Token'ın süresinin dolup dolmadığını doğrular. Token geçerli süresi içinde mi, değil mi, bu kontrol edilir.
ValidateIssuerSigningKey = true : Token'ı imzalamak için kullanılan anahtarı doğrular. Token'ın kim tarafından imzalandığını kontrol eder.
ValidIssuer : ValidIssuer, token'ın oluşturucusunun geçerli olup olmadığını kontrol etmek için kullanılır. Bu değer, AppSettings:Issuer ayarından alınır.
ValidAudience : ValidAudience, token'ın hedef kitlesinin geçerli olup olmadığını kontrol etmek için kullanılır. Bu değer, AppSettings:Audience ayarından alınır.
IssuerSigningKey : Bu, token'ı imzalamak için kullanılan anahtardır. SymmetricSecurityKey sınıfı, simetrik bir şifreleme anahtarı oluşturur ve bu anahtar, AppSettings:Token değerinden alınır. Token'ın geçerli bir imza ile oluşturulduğunu doğrulamak için kullanılır.
Authentication işlemimizi de tamamladıktan sonra Api katmanımız içerisine ConfigurationModel adında sınıf oluşturuyoruz.
Sınıfımızı bu şekilde oluşturduktan sonra Program.cs içerisine gelip görseldeki kodu yazıyoruz.
Configure<T>: Bu metod, Dependency Injection için bir seçenekler (options) nesnesi yapılandırır. T burada, ayarları tutacak olan sınıfı belirtir. Burada daha demin oluşturduğumuz ConfigurationModel sınıfımızı yapılandırmamızı sağlıyor.
builder.Configuration.GetSection("AppSettings") GetSection("AppSettings"): Bu metod, appsettings.json dosyasındaki AppSettings adlı bölümü alır. Bu bölüm, uygulamanın yapılandırma ayarlarını içeriyor.
Bind(x): Bu metod, GetSection("AppSettings") ile elde edilen yapılandırma ayarlarını, x ile belirtilen ConfigurationModel sınıfındaki ilgili özelliklere bağlar. Bu sayede appsettings.json dosyasındaki değerler, ConfigurationModel sınıfına otomatik olarak atanır.
Buraya kadar Authentication için gerekli olan tüm işlemleri yaptık.
Sırada Swagger'ı yapılandırıp Authorization işlemini yapmakta.
Program.cs içerisine.
Kod bloğumuzu baştan aşağıya anlayacak olursak:
AddSwaggerGen : Bu metod, Swagger'ı ASP.NET Core uygulamanızda yapılandırmak için kullanılır. Swagger dokümantasyonunu oluşturmak ve ayarlarını yapmak için gereken tüm bileşenleri hizmet koleksiyonuna ekler.
SwaggerDoc : SwaggerDoc metodu, API'nizin bir sürümü için Swagger dokümantasyonu oluşturur.
"v1": API sürümü için kullanılan etiket. Bu, Swagger arayüzünde görüntülenen API sürümünü belirtir.
Title : API'nizin başlığı. Swagger arayüzünde API'nin adı olarak görüntülenir. Örneğin, "TMD Education API".
Version : API'nin sürümünü belirtir. Bu örnekte, "v1" olarak ayarlanmıştır.
AddSecurityDefinition : Bu metod, Swagger dokümantasyonuna bir güvenlik tanımı ekler. Bu güvenlik tanımı, API'ye nasıl kimlik doğrulama yapılacağını belirtir.
"Bearer": Güvenlik tanımının adı. Bu isim, Swagger arayüzünde JWT kimlik doğrulaması için kullanılan şemayı temsil eder.
OpenApiSecurityScheme : Bu sınıf, Swagger'da kullanılan güvenlik şemasını tanımlar.
In = ParameterLocation.Header : JWT token'ının HTTP isteğinin başlığında (Authorization başlığı altında) bulunacağını belirtir.
Description : JWT kimlik doğrulamasının nasıl kullanılacağını açıklayan bir açıklama sağlar. Bu açıklama Swagger arayüzünde görüntülenir.
Name = "Authorization": Bu, JWT token'ının gönderileceği başlığın adıdır. Genellikle bu başlık "Authorization" olarak adlandırılır.
Type = SecuritySchemeType.Http : Güvenlik şemasının türünü belirtir. Burada Http olarak ayarlanmış, çünkü JWT token'ı HTTP üzerinden iletilir.
BearerFormat = "JWT": Bearer token'ın formatını belirtir. Bu durumda, token formatı JWT'dir.
Scheme = "bearer": Bu, kullanılan şemayı belirtir. "bearer" şeması, HTTP Authorization başlığında bir Bearer token gönderileceğini ifade eder.
AddSecurityRequirement : Bu metod, Swagger dokümantasyonunda belirtilen güvenlik gereksinimlerini tanımlar. API'yi çağırmadan önce hangi güvenlik önlemlerinin yerine getirilmesi gerektiğini belirtir.
OpenApiSecurityRequirement : Bu sınıf, API'de güvenlik gereksinimlerini tanımlar.
OpenApiSecurityScheme : Bu, Swagger'daki belirli bir güvenlik şemasını temsil eder.
Reference : Swagger dokümantasyonunda tanımlanmış bir güvenlik şemasına referans verir.
Type = ReferenceType.SecurityScheme : Bu, referansın bir güvenlik şemasına ait olduğunu belirtir.
Id = "Bearer": Bu, yukarıda tanımladığımız "Bearer" şemasına referans verir.
new string[] { }: Bu boş dizi, belirli bir kapsam (scope) gerektirmediğini gösterir. Yani, bu kimlik doğrulama için ekstra bir yetkilendirme gereksinimi yoktur.
Bu işlemleri de yaptıktan sonra son bir işlemimiz kalıyor. Program.cs içerisine yazdığımız kod bloklarından sonra bu iki kod satırını yazmamız gerekiyor.
Burada DİKKAT EDİLMESİ GEREKEN NOKTA bu iki methodun kullanım sırası çok önemli sebebi ise :
Kimlik Doğrulama : app.UseAuthorization() çalışmadan önce, kullanıcının kimliğinin doğrulanması gerekir. app.UseAuthentication() bu doğrulamayı yapar ve HttpContext.User nesnesini ayarlar.
Yetkilendirme : app.UseAuthorization() çalışırken, kullanıcının kimliği (identity) ve rolleri bu HttpContext.User nesnesinden alınır. Eğer app.UseAuthentication() daha önce çalışmamışsa, HttpContext.User nesnesi boş olacak ve yetkilendirme kontrolleri doğru bir şekilde yapılamayacaktır.
Middleware Sırası : ASP.NET Core'da middleware'ler, HttpContext üzerinde sırasıyla işlem yapar. Eğer app.UseAuthorization() önce çalışırsa, HttpContext.User henüz ayarlanmamış olacağından, yetkilendirme işlemi başarısız olur veya yanlış sonuçlar verir.
Bu yazıda JWT Nedir?, Kullanımı, Authentication, Authorization konularını birlikte inceledik diğer yazılarımda görüşmez üzere. Elinize Kuvvet.!
Comments (2)
elifsays:
Eylül 3, 2024 at 2:05 pmMakaleniz oldukça açıklayıcı ve yön gösterici olmuş elinize sağlık
guvenrdvansays:
Eylül 4, 2024 at 8:10 amTeşekkürler, Kolay gelsin.