Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core Identity – Kullanıcının Cookie Değerini Yenileme

Merhaba,

Asp.NET Core Identity mekanizması kimliği doğrulanmış kullanıcının oturum bilgileriyle birlikte mevcut olan tüm rollerini, yetkilerini ve hatta claim değerlerini ilgili kullanıcıya dair hususi olarak oluşturduğu cookie anahtar değerinde tutmakta ve ihtiyaç doğrultusunda bu değer üzerinden istenilen bilgiyi elde etmemizi sağlamaktadır. Dolayısıyla kullanıcı için oluşturulan bu cookie değeri, oturum süresi boyunca sistem tarafından kullanıcının sınırlılıklarının algılanmasını sağlayarak rol, claim yahut politika bazlı yetkilendirme süreçlerinde erişim durumunu değerlendirmektedir. İşte bu durum olası bir açığa kapı aralamaktadır. Şimdi gelin buradaki açığın ne olduğunu ve çözüm olarak ise nasıl refleks geliştireceğimizi inceleyelim.

Cookie Bazlı Yetkilendirmenin Olası Açığı Nedir?
Gelişmiş web uygulamalarında kullanıcı yönetimleri genellikle bir panel üzerinden gerçekleştirilmekte ve anlık olarak kullanıcılara dair yetki, claim yahut role tanımlaması gerçekleştirilebilmektedir. Anlık olarak gerçekleştirilen rol atamalarında hedef kullanıcının önceden oluşturduğu ve farklı yetkiye sahip olan cookie değerini ezmez ya da geçersiz kılmazsak eğer kullanıcı, eski yetkileriyle donatılmış mevcudiyetteki cookie değeri ile oturum süresi bitinceye denk uygulamada tüm erişimleri sağlamaya devam edecektir. Buda acil durumlarda alınan ya da atanan yetkilerin ilgili kullanıcıya oturumu açık olduğu süreçte yansıtılmaması sonucu ortaya çıkabilecek bir zarurettir.

Bunun için aşağıdaki görseli inceleyebilirsiniz;
Asp.NET Core Identity - Kullanıcının Cookie Değerini Yenileme
Görselde de görüldüğü üzere sol taraftaki oturum yöneticiyi, sağ taraftaki oturum ise yetkilendirilmiş kullanıcıyı temsil etmektedir. Kullanıcının tam yetkiyle donatılmış oturumu açık olduğu esnada yönetici tarafından yapılan herhangi bir yetki müdahalesi neticesinde bu durum kullanıcıya anında yansıtılmamakta, dolayısıyla eski yetkileriyle sisteme erişime devam edebilmektedir. Bu durum, acil yetkilerin alınması gerektiği durumlarda yaratacağı etkiler açısından en iyi netice veri kaybıyla sonuçlanacakken, uygulamaya dair kritik arz eden konfigürasyonlara temas edilmesi yahut yasal duvarların aşılacağı binbir türlü kişisel verilerin çalınması vs. gibi durumların da meydana gelmesi/gelebilmesi gibi kötü sonuçların doğmasıda ihtimaller dahilindedir.

Kullanıcının Cookie Değerini Yenileme
İşte böyle bir duruma istinaden kullanıcıların yetkileri değiştirilir değiştirilmez mevcut cookie değerlerinin ezilerek yerine yenisinin oluşturulması gerekmektedir. Bunun için stratejik olarak kullanıcının her yaptığı istek neticesinde o anki mevcut yetkilerini barındıran yeni bir cookie değeri üretilmesi bu işlem için en doğrusu olacaktır.

Peki nasıl yapacağız?
Bir filtre yazarak her istek neticesinde araya girip yeni cookie üretimini gerçekleştirebiliriz. Şöyle ki;

    public class RefreshLoginAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context">Mevcut context nesnesidir.</param>
        /// <param name="next">İstek gönderilen action'ı temsil eden delegate'tir.</param>
        /// <returns></returns>
        async public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (context.HttpContext.User == null)
                return;

            //UserManager nesnesini elde ediyoruz.
            UserManager<AppUser> userManager = context.HttpContext.RequestServices.GetService(typeof(UserManager<AppUser>)) as UserManager<AppUser>;

            //SignInManager nesnesini elde ediyoruz.
            SignInManager<AppUser> signInManager = context.HttpContext.RequestServices.GetService(typeof(SignInManager<AppUser>)) as SignInManager<AppUser>;

            //User'ı elde ediyoruz.
            AppUser user = await userManager.GetUserAsync(context.HttpContext.User);
            
            if (signInManager.IsSignedIn(context.HttpContext.User))
            {
                //Eğer user sign olmuşsa ilgili kullanıcının cookie değerini refresh ediyoruz.
                await signInManager.RefreshSignInAsync(user);
            }

            //Hedef action'a akışı bırakıyoruz.
            await next();
        }
    }

Oluşturulan bu filtreyi aşağıdaki gibi hedef controllerlarda kullanabiliriz.

    [Authorize(Roles = "Administrator, Moderator, Editor")]
    [RefreshLogin]
    public class HomeController : Controller
    {
    [Authorize(Roles = "Administrator")]
    [RefreshLogin]
    public class CategoriesController : Controller
    {
    [Authorize(Roles = "Administrator")]
    [RefreshLogin]
    public class UsesController : Controller
    {
    [Authorize(Roles = "Administrator")]
    [RefreshLogin]
    public class RolesController : Controller
    {
    [Authorize()]
    [RefreshLogin]
    public class ProductsController : Controller
    {
    [Authorize(Roles = "Administrator, Moderator")]
    [RefreshLogin]
    public class CommentsController : Controller
    {

Böylece yapılan her istek neticesinde ‘RefreshLogin’ attribute’u tetiklenecek ve ‘RefreshSignInAsync’ metodu ile ilgili kullanıcının cookie değerini güncel roller ve yetkilerle güncelleyecektir.

Asp.NET Core Identity - Kullanıcının Cookie Değerini Yenileme

Küçük Bir İstişare
Oluşturulan ‘RefreshLogin’ attribute’u sürekli tüm isteklerde yeni cookie oluşturmaktadır. Bu yapılacak en küçük işlemler içinde geçerli olacağından dolayı ekstradan maliyet söz konusu olabilmektedir. Buradaki maliyeti biraz daha ekonomik hale getirebilmek için ilgili kullanıcı için veritabanında yetki atamaya dair bildiri barındıran bir kolonda durum bilgisini tutabilir ve buraya yapılan check neticesinde yeni cookie üretimini gerçekleştirebilirsiniz.

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

Bunlar da hoşunuza gidebilir...

7 Cevaplar

  1. Ahmet Gültekin dedi ki:

    Merhabalar,
    .net core 3.1 ile sitenizdeki identity konularını inceleyerek bir sipariş alma sistemi yazdım. Yanlız şuanda bazen oturum açma işlemlerinde çerez kullanılmasından kaynaklı bir sorun yaşıyorum. Oluşturulan çerez non-ascii bir karekter içerdiğinde Kestrel sunucuda sorun yaşatıyor. Konuyla ilgili araştırmalarda bi çözüme varamadım. Bazı yazılımcıların yazdığına göre Kestrel sunucuya non-ascii bir çerez gönderimine bu sorun çıktığıdır. Oluşturan çerezleri manuel silip tekrar oturum açmayı denediğimde çoğunlukla giriş yapabiliyorum. Bazende hata tekrarlanıyor.
    Hatayı çözmemde yardımcı olabilirseniz çok sevinirim. Kolay gelsin.

    Çıkan hata —————–
    Server Error

    403 – Forbidden: Access is denied.
    You do not have permission to view this directory or page using the credentials that you supplied.

    • Gençay dedi ki:

      Merhaba,

      Üretilen cookie değerini nasıl kullanıyorsunuz. Örnek bir kod bloğu paylaşır mısınız?

      • Ahmet Gültekin dedi ki:

        Cookie değerlerini herhangi bir yerde kullanmıyorum. İdentity nin kendi oluşturduğu cookieler bunlar. Oturum açma ve yetkilendirme durumlarında kullanılıyor. Şuanda sorunu web.config doyasına aşağıdaki eklentiyi yaparak atlatıyorum. ModSecurity devredışı şuanda. güvenlik olarak sorun yaşayacağımı düşünüyorum.

  2. Abdullatif dedi ki:

    Buradaki maliyeti biraz daha ekonomik hale getirebilmek için ilgili kullanıcı için veritabanında yetki atamaya dair bildiri barındıran bir kolonda durum bilgisini tutabilir ve buraya yapılan check neticesinde yeni cookie üretimini gerçekleştirebilirsiniz.

    Hocam burayı anlamadım. Örnekle açıklayabilir misiniz?

    • Huseying dedi ki:

      Yıllar geçmiş ama ben yine de yazayım, AspNetUsers tablosuna IsUserRolesChanged gibi bir kolon eklediğimizi düşünün, bunun değeri nşa’da false olsun. Eğer admin kullanıcının rolünü değişirse bu kolonu true olarak işaretleyelim. Rolü değişen kullanıcı bir istek yaptığında bu kolonun değeri true ise cookie güncellensin ve bu kolonun değeri tekrar false’a çekilsin. Böylelikle gerçekten rolünde değişim olan kullanıcı için bu işlem yapılır ve maliyet azaltılır.

  3. Hasan dedi ki:

    Merhabalar hocam.
    Filter yerine bir middleware yazarak aynı işlemi daha az kodla çözebiliriz sanırım.
    middleware’i uygun bir sıraya yerleştirip, kullanıcı login olmuşsa sizin dediğiniz gibi herhangi bir yetki değimini veri tabanında bir kolon ile tutup, buradan değişim olup olmadığını kontrol ederek bu middleware içersinde (gelen requestin sahibini bulduktan sonra) direk olarak cookie tazeleme işlemini yapsak sanırım filterdan daha az uğraşmış oluruz. Her yere filter girmekten daha mantıklı olabilir. Aklıma böyle bir fikir geldi yapabilirsem en yakın zamanda kodlayıp buraya atacağım.

  1. 10 Mayıs 2020

    […] Asp.NET Core Identity – Kullanıcının Cookie Değerini Yenileme […]

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir