Yazılım Mimarileri ve Tasarım Desenleri Üzerine

Asp.NET Core Identity – Claim Bazlı Kimlik Doğrulama – XVII

Asp.NET Core Identity

Merhaba,

Bu içeriğimizde Asp.NET Core Identity yazı dizimizin 17. makalesi olan Claim Bazlı Kimlik Doğrulama(Claims Based Authorization) yöntemini inceleyeceğiz.

Herşeyden önce kavramsal temelleri oturtabilmek için ilk olarak temel tanımlamalarda bulunmamız gerekmektedir. O halde buyrun Claim’ın ne olduğundan başlayalım.

Claim Nedir?

Claim kelimesinin birçok sözlük anlamı mevcuttur. Bunlar; fiili olarak “talep etmek(f)“, “iddia etmek(f)” olmakla birlikte isim olarak ise “sav(i)“, “istek(i)” yahut “iddia(i)” karşılığına gelmektedir. Yazılımsal açıdan olayı değerlendirdiğimizde ise kullanıcı hakkında key – value şeklinde hususi bilgiler tutan ve bunları bizlere yaptığımız talepler neticesinde getiren bir yapı söz konusudur.

Claim Ne Amaçla Kullanılmaktadır?

Yukarıda bahsedildiği gibi kullanıcı hakkında hususi bilgiler tutabilmek için kullanılmaktadır. Tabi temel amaç bu değildir. Asıl amaç, bu bilgileri yetkilendirme senaryolarından rol bazlı yetkilendirmenin sınırlarını daha da esnetebilmek ve uygulamada işlev görecek olan kullanıcının edindiği rolün dışında özelleştirilmiş kontroller sağlayabilmek için tercih edilmektedir. Söz gelimi bu tarz bir kullanımada Claim Bazlı Yetkilendirme denmektedir.

Neden Claim Bazlı Yetkilendirme Kullanmalıyız?

Bu sorunun cevabını şöyle örneklendirebiliriz; internet üzerinden video hizmeti veren bir web uygulamasını misal olarak ele alalım. Sistem tarafından “İzleyici” rolü atanmış kullanıcılara video hizmeti verildiğini düşünelim. Ayriyetten uygulamada “komedi”, “gerilim” ve “korku” kategorilerinin mevcut olduğunu ve her bir kategorinin belirli bir yaş aralığı tarafından erişilebilir olduğunu düşünelim. Evet, burada her ne kadar rol bazlı yetkilendirme olmuş olsada neticede bu yaş aralığının rol bazlı yetkilendirmeyle ölçülebilmesi pek mümkün değildir. Nihayetinde her bir kategoriye erişim için öncelikli şart “İzleyici” rolünde olunmasıdır lakin her bir kategori başlı başına sisteme giriş yapmış ve “İzleyici” rolünü almış o kullanıcının yaş aralığını kontrol etmeli ve uygunsa erişim sağlamalıdır. İşte burada yaş aralığını ölçebilmek için ilgili kullanıcılara yaş değerlerinin claim olarak atanması sağlanmalı ve claim bazlı bir yetkilendirme yapılmalıdır.

Ya da bir başka örnek vermemiz gerekirse; bir makale sitesinde makaleleri kullanıcılara ödeme yapıp yapmama bilgilerine göre gösterip göstermeme durumu yine claim bazlı bir yetkilendirmenin sayesinde gerçekleşecektir. Nihayetinde burada her bir kullanıcıya atanan “Kullanıcı” rolü ile kullanıcılar tanımlanırken, ödeme bilgisi ise claim ile eklenmekte ve claim tabanlı yetkilendirme ile kontrol edilmektedir.

Yani uzun lafın kısası;

Claimler; rollerin dışında kullanıcı hakkında bilgi tutmamızı ve bu bilgilere göre yetkilendirme yapmamızı sağlayan yapılardır.

Claim Mekanizması Nasıl Çalışmaktadır?

Kullanıcıya dair tanımlanmış ekstra bilgiler olan claimleri kullanarak yetkilendirme işlevini gerçekleştirebilmek için cookie değeri kullanılmaktadır. Sisteme giriş yapacak olan kullanıcıya özel tanımlanmış claimler oluşturulan Cookie değerinin içerisine eklenmekte ve lazım olduğu taktirde oradan erişilmektedir. Burada Peki cookie içerisine claim bilgileri nasıl eklenmektedir? sorunuzu duyar gibiyim… Bu soruya esas cevabı ilerleyen satırlarda pratik olarak vereceğimizden dolayı şimdilik ‘iki farklı yöntemle ekleme yapabiliriz’ şeklinde kısa bir karşılıkla neticelendirelim. Yine de bir iki kelamla teorik olarak bahsetmemiz gerekirse bu iki yöntemden ilki kullanıcıya dair cookie değeri oluşturulurken o anda (dinamik olarak)eklemeyken bir diğeri ise veritabanında kullanıcıyla ilişkisel tutulan claim verilerinin derlenip eklenmesidir.

Velhasıl şimdi biz claim yapılanmasının mekanizmasını somutlaştırmaya devam edelim. Kullanıcıya dair claimlere erişebilmek için aşağıdaki görselde şematize edildiği gibi “System.Security.Claims” napespace’i altında bulunan ClaimsPrincipal türünden olan “User” propertysinin “User.Claims” komutunu kullanabiliriz.

Ayrıca yine aynı namespace altında bulunan “ClaimsIdentity” türünden olan nesne üzerinden ilgili kullanıcının tüm verilerini elde edebilir ve claimlerine erişebiliriz.

Claim Ekleme Yöntemleri

Uygulamaya başarılı bir şekilde giriş gerçekleştiren kullanıcıya “Dinamik Ekleme” ve “Veritabanından Ekleme” olmak üzere o anki ihtiyaca istinaden teknik açıdan farklı iki yöntemle claim dahil edebilmekteyiz. Tabi ki de bu dahil edilen claimler süreçte kullanıcı için cookie bilgilerinde tutulacak ve gerektiği taktirde oradan erişilecektir. Şimdi gelin bu iki yöntemi inceleyelim;

Bu işlemlerden sonra sıra oluşturulan ve uygulamaya dahil edilen bu claim yapılanması ile yetkilendirme işlemini ele almaya geldi.

Claim Bazlı Yetkilendirme

Oluşturulan claimleri kullanarak yetkilendirme yapabilmek için Startup.cs dosyasındaki “ConfigureServices” metodu içerisinde aşağıdaki gibi politika oluşturmalı ve claimlerdeki değerleri belirlediğimiz static değerlerle zorunlu kılmalıyız;

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            .
            .
            .
            services.AddScoped<IClaimsTransformation, UserClaimProvider>();
            services.AddAuthorization(x => x.AddPolicy("UserClaimNamePolicy", policy => policy.RequireClaim("username", "gncy")));
            services.AddAuthorization(x => x.AddPolicy("UserClaimPositionPolicy", policy => policy.RequireClaim("pozisyon", "admin")));
            .
            .
            .
        }
    }

Yukarıdaki kod bloğunu incelerseniz eğer “UserClaimNamePolicy” ve “UserClaimPositionPolicy” olmak üzere iki adet politika oluşturulmuştur ve işlevsel olarak sırasıyla; ilki sistemdeki kullanıcının claimType değeri “username” olan claiminin “gncy” değerinde olmasını ve ikincisinin ise yine sistemdeki kullanıcının “pozisyon” claimType değerindeki claiminin “admin” olmasını şart koşmaktadır.

Bu politikaları kullanabilmek için Politika Bazlı Kimlik Doğrulama makalesinde ele alındığı gibi yetkilendirilecek action ya da controllerları ilgili politikalarla işaretlememiz yeterlidir.

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
        [Authorize(Policy = "UserClaimNamePolicy")]
        public IActionResult Page1()
        {
            return View();
        }
        [Authorize(Policy = "UserClaimPositionPolicy")]
        public IActionResult Page2()
        {
            return View();
        }
    }

Yukarıdaki kod bloğunda görüldüğü üzere “Page1” ve “Page2” sayfaları oluşturulan politikalarla işaretlenmiştir ve böylece claim bazlı yetkilendirme gerçekleştirilmiştir. Aşağıdaki ekran görüntüsünde de olduğu gibi sistemdeki kullanıcı rollerin dışında belirtilen politikalar eşliğinde zorunlu kılınan claim değerleri ile başarılı bir şekilde yetkilendirilmekte ve daha geniş ve detaylı bir yönetim sergilenmektedir.

Nihai olarak kullanıcı yetkilendirme senaryolarında rol bazlı yetkilendirmenin dışında claim bazlı yetkilendirmeyi incelemiş ve daha teraffuatlı bir yapılanmanın nasıl inşa edilebileceğini detaylarıyla irdelemiş bulunmaktayız.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Mobil sürümden çık