Makale Özeti

Bu makalemizde OpenID protokolünü inceleyip, ASP.NET MVC web uygulamamızda nasıl kullanabileceğimize bakacağız.

Makale

OpenID Türkçeye “Açık Kimlik” olarak çevrilebilecek yeni bir kimlik doğrulama protokolüdür.  Web’ de tek bir kimlik ile birden çok sisteme erişim sağlamak uzun zamandır üzerinde çalışan bir konu. Zaman zaman web’ deki büyük oyuncular kendi altyapılarını diğer sitelere açarak bu soruna çözüm üretmek istediler. Ancak bu çözümler başarısız oldu, bunun arkasındaki neden hepsinin merkezi olarak kurgulanmalarıydı. Bu yapılarda kullanıcıların ilk önce merkezi sistemde bir kimlik daha yaratmaları gerekiyordu. Kimlik sorununu çözmek için bir kimlik daha yaratmak web kullanıcılarını cezbetmedi.

Peki, OpenID bu soruna nasıl bir çözüm öneriyor?

OpenID dağıtık bir mimaride kimlik doğrulaması yapan sistemler ile kimlik doğrulamasına ihtiyaç duyan sistemler arasında iletişimin nasıl olacağını tanımlar. Ancak kimlik doğrulaması yapan sistemlerin bu işlemi nasıl gerçekleştireceği konusuna karışmaz.  Bunun sonucu olarak isteyen tüm sistemler, ellerinde bulunan kimlikleri OpenID yardımı ile diğer sitelerin kullanımına sunabilirler. Son kullanıcılar ise bu yapı sayesinde zaten var olan kimliklerini OpenID üzerinden doğrulama yapan sitelerde kullanılabilirler.

OpenID nasıl çalışır?

Bir örnek üzerinden OpenID’nin nasıl çalıştığını inceleyelim. İlk önce süreçte yer alacak aktörlerimizi belirleyelim. İlk aktörümüz OpenID destekleyen kimliğini kullanarak bir web sitesine girmek isteyen web kullanıcımız, süreçte ona istemci ismini vereceğiz. Diğer aktörlerimiz ise istemcinin giriş yapmak istediği site (web sitesi) ve OpenID protokolünü destekleyen kimlik doğrulama servisi (kimlik doğrulayıcı).

Süreç şu şekilde işler:

1.      İstemci, web sitesine kullanmak istediği kimlik doğrulayıcı adresini iletir. Bu adres kimlik doğrulayıcının belirlediği genel bir adres olabileceği gibi kimlik doğrulayıcı tarafından istemciye özel üretilmiş bir adreste olabilir. İstemciye özel üretilmiş bu adreslere istemcinin OpenID adresi denir.

2.      Web sitesi, sunucu tarafında kimlik doğrulayıcının belirtilen adresine özel bir keşif isteği gönderir. Bu istek sonucunda kimlik doğrulayıcı süreçte kullanılacak adresi web sitesine iletir.

3.      Web sitesi istemciyi, kimlik doğrulayıcının belirttiği adrese gönderir.

4.      Bu aşamada kimlik doğrulayıcı ile istemci arasında kimlik doğrulaması işlemi gerçekleşir. Bu işlemin nasıl yapıldığı bizim sürecimizi ilgilendirmez.

5.      İşlem sonucunda kimlik doğrulayıcı, doğrulama işlemi sonucu ile birlikte istemciyi tekrar web sitesine yönlendirir. Bu yönlendirme sırasında kimlik bilgileri hem açık olarak hem de şifrelenmiş olarak web sitesine taşınır.

6.      Web sitesi eğer kimlik doğrulama işlemi sonucu olumlu ise, verilerin doğruluğundan emin olmak için sunucu taraflı olarak kimlik doğrulayıcıya bir kontrol isteği gönderir. Kontrol isteğinin içerisinde bir önceki adımda alınan kimlik bilgilerinin açık ve şifreli metinleri yer alır.

7.      Kimlik doğrulayıcı sistem gelen istekteki şifreli veriyi çözer ve açık veri ile uyuşması durumunda web sitesine bilgilerin doğruluğunu onaylayan bir yanıt gönderir.

8.      Web sitesi kimlik bilgilerinin doğruluğunda emin olur ve süreç tamamlanır.

ASP.NET MVC uygulamamızda OpenID’yi nasıl kullanabiliriz?

Uygulamamızda stackoverflow gibi birçok site tarafından da kullanılan açık kaynak kodlu DotNetOpenAuth kütüphanesini kullanacağız. Bu kütüphaneyi http://www.dotnetopenauth.net/ adresinden indirebilirsiniz.

Örneğimize “Internet” şablonunu kullanarak bir ASP.NET MVC 3 uygulaması yaratarak başlıyoruz. Kütüphaneyi kullanmamız için gerekli olan DotNetOpenAuth.dll dosyasını projemize referans olarak ekliyoruz.

Uygulamamızda akışı şu şekilde kurgulayacağız. Kullanıcı sağ üst köşede yer alan “Log On” linkine bastığında openid adresini girebileceği bir form ile karşılaşacak. Bu form’a girdiği OpenId bilgisi ile kimlik doğrulayıcı servisinden kullanıcının kimlik bilgisi doğrulanacak ve son olarak kullanıcı ana sayfaya yönlendirilecek.

İlk olarak kullanıcının OpenId bilgisini taşıyacak olan modelimizi aşağıdaki şekilde hazırlayalım.

    public class OpenIdModel
    {
        [Required]
        [Display(Name = "OpenId")]
        public string OpenId { getset; }
    }

 

Sonrasında bu formu gösterecek kodumuzu hazırlıyoruz. Bunun için OpenId isimli bir controller sınıfı yapıp, index action’ında formumuzu göstereceğiz.

    public class OpenIdController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

 

OpenIdController

 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
 
<h2>Index</h2>
 
<script src="<%: Url.Content("~/Scripts/jquery.validate.min.js")  %>" type="text/javascript"></script>
<script src="<%: Url.Content ("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script>
 
<% using (Html.BeginForm("LogOn""OpenId")) { %>
    <%: Html.ValidationSummary(true%>
    <fieldset>
        <legend>OpenIdModel</legend>
 
        <div class="editor-label">
            <%: Html.LabelFor(model => model.OpenId)  %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.OpenId)  %>
            <%: Html.ValidationMessageFor (model => model.OpenId) %>
        </div>
 
        <p>
            <input type="submit" value="Giriş" />
        </p>
    </fieldset>
<% } %>
 
</asp:Content>

 

OpenId/Index  view

Ayrıca LogOnUserControl.ascx içerisindeki “Log On” linkini de aşağıdaki şekilde değiştirerek yarattığımız action’a yönlendiriyoruz.

<%: Html.ActionLink("Log On""Index""OpenId"%> ]

 

Bundan sonra yapmamız gerek formumuzu gönderdiğimiz ve asıl openid sürecini işletecek olan OpenId action’ımızı yazmak.  Bu fonksiyonda gerçekleştirdiğimiz işlemleri açıklama olarak kodun üzerine ekledim.

 // DotNetOpenAuth kütüphanesinin openid sürecini yöneten sınıfı
        private static readonly OpenIdRelyingParty openid = new OpenIdRelyingParty();
 
        // Bu action iki şekilde çağrılıyor.
        // 1. Uygulamamızda Index view'ı üzerinden form post edildiğinde
        // 2. OpenId kimlik doğrulayıcı sistem kullanıcıyı tekrar uygulamamıza y önlendirdiğinde
        public ActionResult LogOn(OpenIdModel model)
        {
            // Action'ın ne şekilde çağrıldığını openid formatında bir response var& nbsp;mı diye kontrol ediyoruz.
            // Eğer yok ise Index formundan buraya geldik.
            var response = openid.GetResponse();
            if (response == null)
            {
                Identifier id;
                // Form'dan gönderilen adres bir openid identifier olarak algılanabiliyor&nbs p;mu?
                if (Identifier.TryParse(model.OpenId, out id))
                {
                    try
                    {
                        ; // Kullanıcının belirttiği adrese uygun bir istek yaratalım.
                        ; // Eğer adres openid kimlik doğrulayıcısı olarak çözülemezse hata oluşac aktır.
                        ; IAuthenticationRequest authenticationRequest = openid.CreateRequest(model.OpenId);
 
                        ; // Kimlik doğrulayıcı sisteme kullanıcının email ve isim bilgisini isted iğimizi iletelim.
                        ; // Zorunlu olarak istesekte kimlik doğrulayıcı sistem bu bilgiyi gönderm eyebilir !!
                        ; FetchRequest extension = new FetchRequest();
                        ; extension.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
                        ; extension.Attributes.AddOptional(WellKnownAttributes.Name.FullName);
                        ; 
                        ; authenticationRequest.AddExtension(extension);
 
                        ; // Kimlik doğrulaması için kullanıcıyı kimlik doğrulama sistemine yönlendirel im.
                        ; return authenticationRequest.RedirectingResponse.AsActionResult();
                    }
                    catch (ProtocolException ex)
                    {
                        ; // Kimlik doğrulama servisine uygun bir istek yaratırken hata oluştu.
                        ; // OpenId EndPoint bulunamamış olabilir.
                        ; ModelState.AddModelError(string.Empty,  ex.Message);
                        ; return View("Index", model);
                    }
                }
                else
                {
                    // Verilen adresten identifier oluşturamadık.
                    ModelState.AddMod elError(string.Empty, "Adres openid olarak tanınmıyor.");
                    return View("Index", model);
                }
            }
            else
            {
                // Burada elimizde bir openid response var. 
                // Bu kullanıcının kimlik doğrulayıcı servisten geldiğini gösterir.
                switch (response.Status)
                {
                    // Kullanıcı kimlik doğrulayıcı serviste işlemi başarı ile tamamlamış.
                    case AuthenticationStatus.Authenticated:
                        ; ViewBag.FriendlyIdentifier = response.FriendlyIdentifierForDisplay;
 
                        ; // İstediğimiz ekstra bilgileri kontrol edelim.
                        ; var fetchResponse = response.GetExtension<FetchResponse>();
                        ; if (fetchResponse != null)
                        ; {
                        ;     ViewBag.MailAddress = fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email);
                        ;     ViewBag.Name = fetchResponse.GetAttributeValue(WellKnownAttributes.Name.FullName);
 
                        ; }
 
                        ; FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);
                        ; return RedirectToAction("Index""Home");
                    // Kimlik doğrulama işlemi kimlik doğrulayıcı sistemde iptal edilmiş.< br>                     case AuthenticationStatus.Canceled:
                        ; ModelState.AddModelError(string.Empty, "Kimlik doğrulayıcıda iptal edildi.");
                        ; return View("Index", model);
                    // Kimlik doğrulama işlemi kimlik doğrulayıcı sistemde başarısız olmuş.
                    case AuthenticationStatus.Failed:
                        ; ModelState.AddModelError(string.Empty, "Kimlik doğrulayıcıda başarısız oldu.");
                        ; return View("Index", model);
                }
            }
            return new EmptyResult();
        }

 

Böylece uygulamamıza OpenId ile kimlik doğrulama sistemini eklemiş olduk. Bu makalede geliştirdiğimiz projeyi http://dl.dropbox.com/u/11429547/OpenIdReplyingParty.zip adresinden indirebilirsiniz.

 

Erdem Ergin

http://about.me/erdemergin

http://erdem.ergin.co