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

OpenIddict #1 – OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?

Merhaba,

Bu içeriğimizde Asp.NET Core uygulamalarında OAuth 2.0/OpenID Connect server’ları oluşturmak için tasarlanmış olan ve açık kaynak olarak geliştirilen OpenIddict Framework’ünü ele alıyor olacağız.

OpenIddict Nedir?

OpenIddict ilk olarak 2015 yılında temelleri atılmış olan ve OpenID Connect server kurmak için çözüm sağlayan bir kütüphanedir. Identity Server‘a nazaran biraz daha düşük seviyede işlevselliğe sahiptir.

Neden IdentityServer4 Yerine OpenIddict’i Kullanmalıyız?

Yıllarca .NET çatısı altında OAuth2 + OpenID Connect protokolleri eşliğinde güvenli bir token hizmeti sağlamak için IdentityServer kütüphanesinden istifade ettiğimize çoğunuz vakıftır. Lakin IdentityServer, gelecek sürümleri lisanslamaya karar verdiğinden dolayı, bu durum ticari uygulamalar için ekstradan maliyet kalemi olarak projelerimize yansımış bulunmaktadır. Her ne kadar iyi bir yazılım için ekstradan ödeme yapmak pek çok proje veya şirket için bir sorun teşkil etmese de, yine de bir alternatif aramanın zamanının geldiğini düşünmedik değil. Haliyle yaptığımız ufak araştırmalar neticesinde OpenIddict kütüphanesiyle karşılaştık. Denedik, test ettik. Bir nebze eksikliklerini gözlemlediysekte, basit ama etkili olduğuna kanaat getirdik. Ayrıca var olan bir ticari projemizde bu kütüphaneyi sahada tecrübe etme şansımız oldu. Nihayetinde edindiğimiz kazanımlar eşliğinde ve bu kütüphanenin tüm teferruatlarını bütünsel olarak derleyip bir yazı serisi olarak sizlere aktarmanın kararını vermiş bulunuyoruz.

OAuth2 ve OpenID Connect Nedir?(Hatırlayalım)

Esasında bu kavramları IdentityServer4 Nedir? OAuth 2.0 ve OpenID Connect Protokolleri Nelerdir? başlıklı yazımızda tam teferruatlı izah etmiş bulunuyoruz. Yine de usul gereği bu içeriğimizde hafiften özetlememiz gerekirse eğer; OAuth 2.0, uygulamalar arası veri transferinde kullanılan açık bir yetkilendirme(authorization) protokolüyken, OpenID Connect ise bir protokolden ziyade OAuth 2.0 üzerinde kimlik doğrulama(authentication) işlemlerini üstlenen bir katmandır.

OpenIddict Nasıl Çalışır?

Teknik olarak kullanıcı adı ve şifre doğrulamalarını harici bir provider olan authorization server üzerinden gerçekleştirdikten sonra, OAuth2 ve OpenID Connect akışları(flows) için OpenIddict devreye girmektedir. Bu akışlar diğer uygulamalar(clients) tarafından desteklenmekte ve temel olarak bu client’ları kullanan kullanıcılar için yetkilendirmeleri gerçekleştirmektedir.

Burada süreç şöyle cereyan etmektedir. Kullanıcı, authorization server tarafından yetki kontrolü sağlanan bir kaynağa client üzerinden erişmek istediği zaman önce bu kullanıcı client tarafından authorization server’a yönlendirilir. Kullanıcı gerekli authentication’ı sağlarsa eğer kaynağa erişebilmesi için yetkisinin olup olmadığı değerlendirilerek, duruma göre erişimi gerçekleştirilecek ya da gerçekleştirilmeyecektir.

Authorization Server Oluşturma

Şimdi bu içeriğimizde bir Authorization Server için minimum kurulum gerektirecek şekilde uygulama inşa ederek sonraki içeriklere temel oluşturacağız.

Authorization Server için login işlemi yapabileceğimiz bir sayfanın olması gayet yerinde olacaktır. Haliyle biz bu uygulamayı Asp.NET Core MVC mimarisinde tasarlamayı tercih ediyoruz.

  • Adım 1 | (Asp.NET Core MVC Uygulamasının Oluşturulması)
    OpenIddict #1 - OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?İlk olarak ismini istediğiniz şekilde belirtebileceğiniz bir Asp.NET Core MVC uygulaması oluşturalım. Bizlerin, bu serinin sonraki içeriklerinde geliştireceğimiz tüm uygulamaları bu solution altında toparlayacağımızı şimdiden bildirmekte fayda var.

    O yüzden solution adına ‘OpenIddict’ ve Authorization Server uygulamasına da ‘OpenIddict.AuthorizationServer’ adını vermiş bulunmaktayız.

  • Adım 2 | (Local Sertifikanın Yüklenmesi)
    OpenIddict local’de çalışırken bile sertifika gerektirebilmektedir. Bu yüzden local certificate’in güvenilir olduğundan emin olmak için ilgili proje dizininde powershell üzerinden aşağıdaki talimatın verilmesi yeterlidir.

    dotnet dev-certs https --trust

    OpenIddict #1 - OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?

  • Adım 3 | (Kimlik Doğrulamayı-Authentication- Etkinleştirme)
    Şimdi oluşturduğumuz uygulamanın kimlik doğrulama(authentication) özelliğini aktifleştirelim. Bunun için ‘Program.cs’ dosyası içerisinde aşağıdaki çalışmayı gerçekleştirelim.

    .
    .
    .
    builder.Services.AddControllersWithViews();
    
    builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => options.LoginPath = "/account/login");
    .
    .
    .
    

    Yukarıdaki kod bloğunu incelerseniz bu MVC temelli uygulamamız için Cookie bazlı authentication operasyonunu gerçekleştirmiş bulunmaktayız. Ve ayrıca dikkat ederseniz ‘/account/login’ adresi login işlemleri için ayarlanmıştır.

    Bu yapılandırmadan sonra aşağıdaki gibi ‘UseAuthentication’ middleware’ini uygun yerde çağırmamız gerekmektedir.

    .
    .
    .
    app.UseRouting();
    
    app.UseAuthentication();
    
    app.UseAuthorization();
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    .
    .
    .
    
  • Adım 4 | (Login Sayfasının Tasarlanması)
    Artık authentication’ı etkinleştirdiğimize göre kullanıcıların kimliğini doğrulaması için bir login sayfasına ihtiyacımız olacaktır. Bunun için öncelikle kullanıcının kimlik doğrulaması için ihtiyaç duyulan bilgileri içeren viewmodel nesnesini tasarlayarak başlayalım.

    namespace OpenIddict.AuthorizationServer.ViewModels
    {
        public class LoginVM
        {
            [Required]
            public string Username { get; set; }
            [Required]
            public string Password { get; set; }
        }
    }
    

    Ardından kimlik doğrulama sorumluluğunu üstlenecek olan ‘AccountController’ sınıfını aşağıdaki gibi tasarlayalım.

    namespace OpenIddict.AuthorizationServer.Controllers
    {
        public class AccountController : Controller
        {
            [HttpGet]
            public IActionResult Login(string returnUrl)
            {
                TempData["returnUrl"] = returnUrl;
                return View();
            }
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public async Task<IActionResult> Login(LoginVM model)
            {
                if (ModelState.IsValid)
                {
                    List<Claim> claims = new() { new(ClaimTypes.Name, model.Username) };
                    ClaimsIdentity identity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                    ClaimsPrincipal principal = new(identity);
                    await HttpContext.SignInAsync(principal);
    
                    if (Url.IsLocalUrl(TempData["returnUrl"]?.ToString()))
                        return Redirect(TempData["returnUrl"].ToString());
    
                    return RedirectToAction("Index", "Home");
                }
    
                return View(model);
            }
    
            public async Task<IActionResult> Logout()
            {
                await HttpContext.SignOutAsync();
                return RedirectToAction("Index", "Home");
            }
        }
    }
    

    Yukarıdaki örneği incelerseniz eğer 14 ile 30. satır aralığında kimlik doğrulamanın farazi olarak gerçekleştirildiğini kabul ediyoruz. Normal şartlarda burada ‘LoginVM’den gelen verileri veritabanından doğrulayıp ona göre aksiyon almanız gerekmektedir. Bizler içeriği şişirmemek adına buraları es geçiyor ve direkt olarak gelen bilgilere göre bir oturum açma işlemi gerçekleştiriyoruz. 19. satıra bakarsanız eğer CookieAuthenticationDefaults.AuthenticationScheme ile Cookie authentication şemasını belirtiyoruz. 21. satırdaki SignInAsync metodu ise ‘CookieAuthenticationHandler’ı çağıran ve login neticesinde üretilecek değeri cookie’ye yerleştirip signin yapmamızı sağlayacak olan bir extension metottur. Aynı şekilde 34. satırda SignOutAsync metodu ile signout işlemini gerçekleştiriyoruz.

    Bu adımın sonuncu hamlesi olarak ‘Login’ action’ının view’ini aşağıdaki gibi tasarlayalım.

    @model OpenIddict.AuthorizationServer.ViewModels.LoginVM
    <form autocomplete="off" asp-route="Login">
        <div class="card">
            <input type="text" class="form-control form-control-lg" placeholder="Username" asp-for="Username" autofocus>
            <input type="password" class="form-control form-control-lg form-control-last" placeholder="Password" asp-for="Password">
        </div>
        <p>
            <button type="submit" class="btn btn-dark btn-block mt-3">Login</button>
        </p>
    </form>
    
  • Adım 5 | (Anasayfayı Güncellemek)
    Son olarak, kimliği doğrulanmamış kullanıcılar için anasayfada gerekli güncellemeleri gerçekleştirelim. Bunun için ‘HomeController’ın ‘Index’ action’ının view’ine gelelim ve aşağıdaki çalışmayı icra edelim.

    @using Microsoft.AspNetCore.Authentication
    @if (User.Identity.IsAuthenticated)
    {
        var authenticationResult = await Context.AuthenticateAsync();
        var issued = authenticationResult.Properties.Items[".issued"];
        var expires = authenticationResult.Properties.Items[".expires"];
    
        <div>
            <h2>@User.Identity.Name </h2>
            <p>olarak oturum açtınız.</p>
            <hr />
            <dl>
                <dt>Issued</dt>
                <dd>@issued</dd>
                <dt>Expires</dt>
                <dd>@expires</dd>
            </dl>
            <hr />
            <p><a class="btn btn-dark" asp-controller="Account" asp-action="Logout">Çıkış yap</a></p>
    
        </div>
    }
    
    @if (!User.Identity.IsAuthenticated)
    {
        <div>
            <p>Oturum açmalısınız!</p>
            <p><a class="btn btn-sm btn-dark" asp-controller="Account" asp-action="Login">Oturum aç</a></p>
        </div>
    }
    

    Eğer ki, kullanıcı authenticated olduysa belli başlı bilgilerini ekranda gösteriyoruz. Yok eğer authenticated olmadıysa, oturum açma sayfasına götüren bir buton yerleştirerek kullanıcıyı yönlendiriyoruz. Tabi ki de sizler daha farklı bir şekilde tasarım gerçekleştirebilirsiniz 🙂

    Uygulama başlatıldığında :
    OpenIddict #1 - OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?
    Oturum açarken :
    OpenIddict #1 - OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?
    ve
    Oturum açıldıktan sonra :
    OpenIddict #1 - OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?

Netice itibariyle;
Artık elimizde authentication ile çalışan temel bir Asp.NET Core MVC projemiz mevcuttur. Bundan sonraki içeriklerimizde OpenIddict ile yapacağımız çalışmalarda bu uygulama üzerinden temel yetkilendirme operasyonlarını gerçekleştiriyor olacağız.

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

Not : Örnek uygulamanın kaynak kodlarına aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/OpenIddict-Authorization-Server-Example

Bunlar da hoşunuza gidebilir...

6 Cevaplar

  1. Nuh dedi ki:

    Tam olarak aradigim konu kalbine mi dogdu mubarek 6 gun once yazmissin 😀

  2. Furkan Aykan dedi ki:

    Hocam merhaba
    .Net Core 2.0 da kullandığım OpenIdDict i .Net Core 3.1 için uyumlu hale getirmek istiyorum OpenIddict kütüphanesinde belirtilen adımları denedim ama başarılı bir sonuç alamadım. Daha doğrusu MVC için bir açıklama bulabildim ama benim projem backende .net front da Angular kullanıyor bu duruma uygun halde bir yapı kuramadım bir tavsiyeniz olur mu acaba.

  1. 22 Eylül 2022

    […] teknik olarak adım adım örneklendiriyor olacağız. Bunun için önceki makalemizde(bknz : OpenIddict Nedir? ve Authorization Server Nasıl Kurulur?) oluşturmuş olduğumuz Authorization Server uygulamasını github adresinden çekip, aşağıdaki […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir