Asp.Net Web API – Token Based Authentication

Bunlar da hoşunuza gidebilir...

123 Cevaplar

  1. Enes Sefa dedi ki:

    Emeğine sağlık çok faydalı oldu

  2. necati dedi ki:

    Makale çok güzel, ellerinize sağlık. Benim bir sorum olacak, postman’la değil de js ile bu işlemleri yapmak istediğimde;
    OPTIONS http://localhost:49516/Api/Students 405 (Method Not Allowed)jQuery.ajaxTransport.options.send @ jquery.js:9664jQuery.extend.ajax @ jquery.js:9215(anonymous function) @ app.js:32
    index.html:1 XMLHttpRequest cannot load http://localhost:49516/Api/Students. Response for preflight has invalid HTTP status code 405

    hatası alıyorum. Token alıp headers kısmından yolluyorum.

  3. Güzel ve anlaşılır olmuş. Anlatımına sağlık

  4. Eren dedi ki:

    Yazı için teşekkürler. Postman kullanmadan nasıl ajax isteği gönderebileceğimizi anlatabilir misiniz?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, kusura bakmayın geç yanıt için yoğunluktan bakamıyorum bu aralar.

      Aşağıdaki gibi bir ajax isteği ile access token’ı alabilirsiniz.

      < script type="text/javascript">
      function GetToken() {
      $.ajax({
      type: ‘POST’,
      url: ‘/Token’,
      dataType: ‘json’,
      data: { “grant_type”: “password”, “username”: “Gokhan”, “password”: “123456” },
      success: function (response) {
      // Access token’ı bu şekilde alabilirsiniz.
      alert(response.access_token)
      }
      });
      }
      < /script>

  5. Melih dedi ki:

    Merhabalar,

    Öncelikle paylaşımınız için teşekkürler.

    grant_type alanını authorization_code olarak geçtiğimde invalid_grant hatası alıyorum. Bu hatayı düzeltmek için neler yapabilirim?

  6. murat_k dedi ki:

    Merhaba hocam, token request ile dönen JSON nesnesi (access_token, token_type, expires_in) parametrelerini döndürmektedir. Eğer kullanıcı adı ve rollerini de (access_token, token_type, expires_in, username) almak istiyorsak ne yapmalıyız. token bilgisinin yanında username gelsin istiyorsak bunu kodda nereye eklemeliyiz?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba
      client o token bilgileri ile server’a bir request isteği bulunduğunda, eğer token bilgisi geçerli bir token ise SimpleAuthorizationServerProvider class’ının içerisinde kullanıcı bazlı identity oluşturarak “identity.AddClaim(new Claim(“sub”, context.UserName));” satırı ile istediğimiz property’lerini doldurmuştuk. Bu bilgilere server tarafında kullanıcı authentication işleminden geçirildikten sonra ulaşabilirsin. Bu bilgilere ulaşabilmek için ise, System.Web.Http namespace’i altında bulunan User context’i üzerinden ulaşabilirsin. Saygılar.

  7. AbbA dedi ki:

    Merhabalar,
    Oldukça temiz bir iş, ellerinize sağlık. Custom Token Auth dan önce Refresh token konusuna da basit bir örnekle değinirseniz çok daha faydalı olacağı konusundayım. Lakin neden ihtiyaç duyulduğu konusunda bazı durumlarda ikilemde kalıyorum.

    • AbbA dedi ki:

      Replace(parent.comment,”olacağı konusundayım.”,”olacağı kanısındayım.”);

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, teşekkür ederim öncelikle. Dürüst olmak gerekirse bu konulara daha derinlemesine Şubat ayı gibi çıkacak olan Asp.NET Web API kitabımda değiniyorum. O yüzden şimdilik daha fazla makale ekleyemiyorum bu konuda. Kısaca ihtiyaç duyulma sebebine değinecek olursak: Eğer belirli bir expire süresine sahipse token fakat API’ı consume eden client hala session’a ihtiyacı varsa, tekrardan login olma ihtiyacı yerine refresh token ile yeni bir authorization token isteğinde bulunarak gerçekleştirebilir. Bu sayede client username ve password gibi bilgileri token lifecycle’ı boyunca tekrardan taşımasına ve validation yapmasına gerek yoktur.

      Saygılarımla.

      • AbbA dedi ki:

        Merhabalar;
        Piyasaya çıkacak olan kitabınız için şimdiden başarılar diliyorum.Cevabınız için de çok teşekkürler, çok fazla olmuyorsam tam da takıldığım kısım işte burası; Sizin örneğinizde; Bir kullanıcı için, giriş yaptığı sayı kadar (teoride sonsuz) 24 saat geçerli tokenlar üretiyor;

        1) Bu bir güvenlik sıkıntısı doğurmaz mı?
        – Sonuçta servise erişmek için, bir kullanıcının birden fazla token ı olabiliyor. Geçmişe dönük oluşturulmuş tüm tokenları geçersiz kılacak bir yöntem daha mantıklı değil mi? Mesela kullanıcı yeni bir validasyon yaptığında. Ayrıca en önemli problem; Kullanıcı giriş yaptı, 24 saatlik token üretildi, sonra kullanıcı şifresini değişti, ancak üretilen tokenı kullanan ile diğer uygulamalar hala daha kaynaklara erişebilir durumda çünkü token 24 saat geçerli.(içerde her authorize durumunda fazladan bir kontrol yapmıyorsan)

        2) Refresh token ile sürekli kullanıcıdan giriş yapmasını önleyerek kullanıcı bilgilerini güvene alabiliyoruz.
        – Çok iyi de, ben servis sunucusu olarak piyasaya geçerli bir token sunduğumda, uygulama o token ı sürekli refresh ile uzatıp, süresiz olarak kullanıcı kaynaklarına erişim sağlayabilir. Kullanıcı istediği kadar şifresini değiştirsin. (içerde her authorize durumunda fazladan bir kontrol yapmıyorsan)

        Yada ben bu TOKEN olayını yanlış mı anlıyorum.

        • Gökhan Gökalp Gökhan Gökalp dedi ki:

          Merhaba tekrardan, İlk olarak 24 saat olayını olması gereken expire süresi olacak şekilde algılamayın. Bu sadece bir örnek olduğu için o şekilde verdim. 🙂 Sonuçta bu PoC (proof-of-concept)’deki amacım; custom olarak bir token provider nasıl oluşturulur idi. Dediğiniz gibi güvenlik bacağı ise ayrı bir kısımdır. Gerek login aşamasında gerekse de access_token’ın lifecycle’ı boyunca sağlanacak olan. Öte yandan refresh_token’da bir expire süresine sahiptir. Expire süresi boyunca belirlenen expire dahilinde yeni bir access_token alabilir client. Amaçta budur zaten. Refresh_token expire olduğunda ise tekrardan login olup yeni bir access_token alması gerekmektedir.

          İyi günler dilerim.

  8. Ümit dedi ki:

    Merhaba,
    Öncelikle anlatımınız için teşekkürler.
    Sormak istediğim şu; OAuth ile HttpPost attribute’una sahip metodları Authorize edebiliyor muyuz? Bununla ilgili açıklayıcı bir kaynak bulamadım. Cevaplarsanız memnun olurum.

  9. Rıdvan dedi ki:

    Merhaba token uygulamasını birden fazla sunucuda çalıştırdığım taktirde. A sunucusunda aldığı tokenı B sunucusunda nasıl doğrulatabilirim.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba. Bu işlem gerçekleştirebilmek için config’ler içerisine machine key’lerin aynı olarak belirlenmesi gerekmektedir. Yani hem token api üzerinde hemde api’ı kullanacak olan uygulama üzerindeki config’ler, aynı machine keylere sahip olmalıdır. Decription işlemleri için machine key içerisinde bulunan “validationKey” ve “decryptionKey” node’ları kullanılmaktadır. Saygılarımla.

      • Rıdvan dedi ki:

        Peki ben token sahibinin bilgilerine api tarafında nasıl ulaşabilirim.
        Yalnızca token geldi ve method çalıştırmam isteniyor bunu kimin yaptığını loglamak istiyorum.

        • Gökhan Gökalp Gökhan Gökalp dedi ki:

          Tanımlamış olduğun identity’lere api tarafına ilgili token’la gelip valide olduğu zaman, System.Web.Http namespace’i altında bulunan User context’i üzerinden ulaşabilirsin.

  10. fatih dedi ki:

    Makaleniz çok yararlı, bunun için teşekkürler. Benim sorum şu: controller veya action bazında grant işlemini nasıl gerçekleştirebiliriz? Mesela haberleri listeleme metodunu kullanabilsin ama haber ekle metodunu kullanamasın. Kullanıcı grubu bazında bu durumu nasıl gerçekleştirebilirim?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, bu işlemi yapabilmek için client’ı authorize ettikten sonra yeni bir claim eklerken ‘identity.AddClaim(new Claim(“role”, “user”));’ burada istediğiniz custom “role” leri ekleyerek bu “role” değerlerine göre action bazında işlem yapılabilip, yapılamayacağını sınırlayabilirsiniz. [Authorize(Roles = “user”)] gibi. İyi günler dilerim.

  11. Mustafa dedi ki:

    Çok güzel bir makale teşekkürler. Veri alışverişinde Bearer kullanıp encrypt yapabilir miyiz? Yaparsak doğru bir yöntem sayılır mı? Amacım verilerin gizliliği.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba teşekkürler. Evet yapabilirsiniz zaten OAuth 2.0 Authorization Framework’ü ile beraberinde gelen Bearer token bir standardizasyon haline gelmiştir. Makale içeriğimiz de buna dayanmaktadır. HTTP protokolü söz konusu olduğu için verilerin gizliliği ne kadar sağlanılabilir bu tartışılır ve sizin architectural tasarımınızada bağlı bir etmen bu. Buna ek olarak da SSL kullanımını önerebilirim.

  12. Tuba dedi ki:

    Merhaba,
    Gayet anlaşılır ve faydalı bir paylaşım olmuş, teşekkürler. Bir sorum olacak; Owin de token tam olarak nasıl bir yapıda tutuluyor?

  13. Mehmet dedi ki:

    Merhaba,

    Bu tür Authentication ile ilgili anlamadığım konu, kullanıcı adı ve şifrenin client tarafında oluyor olmasının güvenlik riski oluşturup oluşturmadığıdır. Yani Web uygulamasında AJAX ile Web Api’ye sorgu gönderirken kullanıcı adı ve şifreyi yazıyoruz.

    url: ‘/Token’,
    dataType: ‘json’,
    data: { “grant_type”: “password”, “username”: “Gokhan”, “password”: “123456” },

    Bu güvenlik bilgilerin bilen biri postman, fiddler gibi bir tool ile çok rahat POST veya GET yapabilecek. Benim derdim Web API’min sadece benim sitemden çağrılıyor olmasıdır. Bunu nasıl yapabilirim. Yani http://www.deneme.com/GetUrun/Kategori/7 şeklindeki bir sorgunun sadece deneme.com çatısı altında yapılmasıdır. Başka bir siteden veya tool aracılığıyla kesinlikle çağrılamamasıdır. Çünkü buradaki “7” değerine rastgele değer gönderilerek sunucudaki tüm data çekilebilir.

    Örneğin bir EXE yazarak aşağıdaki URI’daki adana ifadesi yerine kelimeler yazarak birçok kez call edebiliyorum. Bunu engellemek mümkün mü. HTTP üzerinde özel header mi yazmak gerekiyor Veya Session nesnesi falan mı kullanmak gerekiyor. Server tarafında aynı süre içerisinde çok sayıda post gelirse engelleme yapabilirim belki.
    https://www.sahibinden.com/ajax/search/phrase?q=adana&categoryId=0&_=461305609903

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, ilk olarak kullanıcı adı ve şifre yolluyoruz kısmındaki düşüncenize gelecek olursak; kişi access token alabilmek için ilk adımda bu authentication api’a bu sorguyu göndermek zorunda ve genelde bu api SSL ile korunmaktadır ve SSL ile korunmasıda önerilmektedir. İkinci olarak da AJAX ile göndermek zorunda da değilsiniz, backend de yapabilirsiniz bu işlemi. Asıl sorunuza gelecek olursak da, aynı domain çatısı altında sorgularınızın sadece çağrılmasını istiyorsanız buda CORS (Cross-Origin) olarak adlandırılıyor ve sadece aynı sizin belirlediğiniz URI çatısında istekler cevaplanabiliyor. Burayı inceleyebilirsiniz.

  14. Mehmet dedi ki:

    SSL ile korunması dış uygulamaların bunu okumasını, HTTP paketlerinin okunmasını engelleyecek ama AJAX içerisinde bana bir fayda sağlayacak mı. Yani kullanıcı adı ve şifreyi POSTMAN’a yazdığım zaman yine çalışacak.

    İkinci konu AJAX ile göndermek zorunda değilsiniz kısmını biraz daha açabilir miyiz. Bunu nasıl engelleyebiliriz. Mobil uygulama tarafında değil de Web uygulaması tarafında örneğin bir buttona tıklandığı zaman AJAX ile Web API çağırdığımızı düşünelim bu durumda backend’e authentication işlemi nasıl olacak.

    CORS olayı için teşekkür ederim, benim için yönlendirici oldu.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Önemli olan zaten dış uygulamaların bunu sniffleyememesi. CORS’u yaparsanız zaten Postman veya Fiddler ile bir istekde bulunamayacaksınız. İkinci olarak da REST API entegrasyonunu bu kadar simple düşünmeyin. Herşeyiniz fontend üzerinden AJAX request’leri ile gelsin, gitsin olamaz ki bu kadar güvenliğe takmış ve önem vermiş durumdaysanız. UI tarafındaki Controller’ınızı bir Gateway olarak düşünün. Artık oradaki business’ınız her neyse, asıl REST API’ınızı consume edecek olan request’ler controller tarafında oluşturabilirsiniz. Bu kısımlar artık sizin yoğurt yiyişiniz ve projenizin mimarı dizaynları ile alakalı bir durum.

  15. ilhan dedi ki:

    Kitabınız çıktı mı acaba

  16. İLHAN dedi ki:

    ASP.NET WEB APİ KİTABINIZ NE ZAMAN ÇIKIYOR

  17. fatih dedi ki:

    Kardeşim eline sağlik cok guzel bir makele olmus.web api ile calismaya basladigimdan beri nasil güvenlik önlemi alacagimi düşünüyordum.kendi sistemime uyguladim sorunsuz bir sekilde calisiyor tsk ederim.küçük bir sorum olacak facebok twitter foursquere gibi sitelerin apileride ayni mantiktami calismaktadir yanitlarsan sevinirim kolay gelsin.

  18. Kemal dedi ki:

    Merhaba Gökhan Bey,

    Sorum direk yazı içeriğiyle ilgili değil ama , günümüzde asp.net mvc kullanılan ticari girişimlerde asp.net mvc’nin hazır sunduğu authentication mekanizması mı kullanılıyor?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, bu çok genel bir soru olmuş. 🙂 Ooradaki developer’in ekmek yiyişi ile alakalı bir durumdur diyeyim. İster .Net içerisinde gelen authentication mekanizmalarını kullanır, ister kendisi custom authentication yapısını geliştirir. Bunu bilemem. 🙂

  19. mehmet dedi ki:

    merhaba anlatımınız için teşekkür ederim ben servislerimi android client tarafında kullanıyorum bu şekilde nasıl güvenli hale getirebilirim android tarafınndan yani java tarafundanmı sabit kullanıcı adı şifre verip tokeni alıp sunucuya tekrar gönderecegim

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, evet app’inizin ilk login ekranında mecburen authentication sunucunuza token key alabilmek için kullanıcı adı ve şifreyi göndermeniz gerekmektedir. Onun dışındaki işlemlerde elde etmiş olduğunuz token ile ilerleyebilirsiniz.

  20. Oğuz dedi ki:

    Merhaba Gökhan bey. Ufak bir sorum olacak.

    1. Büyük çaplı bir Web Projesinde Token güvenliğe ihtiyaç olur mu? Bu güvenlik seviyesi sizce hangi aşamadan sonra gerekli olacaktır? İleride bu projeyi kısmi yada tamamını mobile taşımak gerekirse diye soruyorum…

    2. Tokenları api tarafında nasıl tutmak gerekir sizce? Sonuçta bir ikili yapımız var. Token alan kişi ve Token Key. Bunu Sesion da tutabiliriz yada db ye yazabiliriz.. Sizce hangisi?

    3. Böyle bir Token sistemi ne kadar yorar sistemi? Sürekli her servis çağırımında gidip gidip bakmak gerek kullanıcının Tokenı varmı yok mu? diye..

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhabalar, 1. sorunuz için eğer api based bir sistemle çalışıyorsanız ve internal olan resource’larınızı daha sonra dışarıya extend edecekseniz eğer token based bir güvenliğe ihtiyaç duyabilirsiniz. 2. sorunuz için token’ları api tarafında tutmayacaksınız, token yapisi sizin göndermiş olduğunuz kullanıcı adı ve şifreye ve içerisine extra olarak tanımlamış olduğunuz claims bilgilerine göre machine key’lere bakılarak hash’lenir. Token’ı resource’larınızı kullanacak olan client tarafında tutmalısınız. Token tarzı işlemler için db bazlı bir yerde tutmanızı önermem çünkü çok fazla ihtiyacınız olacak ve her seferinde db’ye erişmek size ek bir maliyet getirecektir. 3. sorunuza gelecek olursak, her servis çağrınızda token apinize gitmeyeceksiniz. Normal resource’larınızın bulunduğu api’de owin’i implemente ettiğinizde token expire süresine veya token key’in olup olmadığına göre orada da kontrol edilmektedir zaten.

      • Oğuz dedi ki:

        Gökhan bey merhabalar. Öncelikle cevabınız için teşekkür ederim. Beki daha önce soruldu belki sorulmadı bilmiyorum. Bir sistem tasarlıyorum. Bir binaya girişte kimlik sorulacak. Ok. Token ile bu işi yaptık. binaya giren herkesten kimlik bilgisini aldık.
        2. olarak bina içindeki her odaya girişte bir kimlik kontrolü daha yapmam lazım. Kapıdan her giren o odaya girmeye yetkili olmayabilir. Yetkisi olsa yada olmasa bile benim x kişisi y odasına girdi bilgisini loglamam gerekli. Bu durumda Token üstünde geçerli kişiyi bulursam işimi görür diye düşünüyorum.

        Sorum
        1. Bu bilgiye nasıl erişirim?
        2. sizin önerebileceğiniz daha farklı bir yapı olur mu? Odaların dinamik olarak sayı ve yetkisinin değişmesi unsurunu göz önünde bulundurursak…

  21. Kerem Akbal dedi ki:

    Öncelikle örnek için teşekkür ederim ancak uygularken bir hata ile karşılaştım.

    using AspNetWebAPIOAuth.OAuth.Providers;

    satırında Provider assembly’sini kabul etmiyor, bahsettiğiniz paketler yüklü ancak build hatası alıyorum.

  22. Özcan dedi ki:

    Merhaba,

    Hocam, birkaç sorum var. Beni bilgilendirebilirseniz sevinirim.

    1 – Dikkatimi çekti. identity.AddClaim(new Claim(“sub”, context.UserName)); ifadesinde “sub” ne anlama geliyor. Birşeyin kısaltılması mı.

    2- Asıl sorum şu; giriş yapılırken oluşturduğumuz bilgilere diğer metodlardan nasıl erişeceğiz. Örneğin kullanıcı giriş yaptıktan sonra kullanıcının mail adresini, adını soyadını da yükleyip sonraki fonksiyonlardan erişmek istiyorum. ,Aşağıdaki sayfada claim okuması gösterilmiş ancak Foreach ile tüm claim’leri listeleyince claimtype alanı hepsi için http://www.w3.org/2001/XMLSchema#string görünüyor.

    https://msdn.microsoft.com/en-us/library/ee517271.aspx

    public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
    bool kullaniciKontrol = KullaniciKontrol(context.UserName, context.Password);
    if (!kullaniciKontrol)
    {
    context.SetError(“invalid_grant”, “Kullanıcı adı veya şifre yanlış.”);
    return Task.FromResult(null);
    }

    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
    identity.AddClaim(new Claim(ClaimTypes.Gender, “Erkek”));
    identity.AddClaim(new Claim(“Sirket”, “Deneme Şirketi”));
    identity.AddClaim(new Claim(“sub”, context.UserName));
    context.Validated(identity);
    return Task.FromResult(null);
    }

    Okuma işlemini de şu şekilde yapıyorum.

    [HttpGet]
    [Authorize]
    public List Liste()
    {
    var identity = (ClaimsIdentity)User.Identity;
    IEnumerable claims = identity.Claims;

    foreach (Claim claim in claims)
    {

    sonuc.Add(“claim.Value: ” + claim.Value);
    sonuc.Add(“claim.ValueType: ” + claim.ValueType);
    }
    return sonuc;
    }

    3 – Son sorum da LOGOUT / SIGNOUT işlemini nasıl yapabiliriz veya belli bir ticket i nasıl sistemden remove edebiliriz.

  23. Özcan dedi ki:

    –DÜZELTME–
    Hocam,

    önceki mesajımdaki 2.soruyu görmezden gelin.
    sonuc.Add(“claim.ValueType: ” + claim.ValueType); ifadesinde ValueType yazmışım oysa sadece Type yazılmalıydı. Gözden kaçmış.

    Şimdi sadece 3 solu sorum için desteğinize ihtiyacım var. LOGOUT işlemini nasıl yapabiliriz veya önceden oluşturulmuş bir token i nasıl geçersiz yapabiliriz.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, daha öncede cevapladığım gibi: “bu tarz session’ları sizin tracklemeniz gerekmektedir. API stateless olduğu için görevi sadece geçerli bir süreye sahip token üretmektir. Handle işlemini unique bir id kaydedip o id üzerinden siz takip edebilirsiniz, logout olduğunda farklı unique bir değer atamak gibi vb. çözümler düşünebilirsiniz. Aktif olmadığı durumlarda ise zaten token expiry olacaktır.”

  24. Serhan erturk dedi ki:

    Merhabalar benim size bir sorum olacak isin icinden cikamaz haldeyim:)
    Requesti atip tokenimizi aldik burada sorun yok. Fakat kullanici sifresi degistiginde veya rol degistiginde degismeden once aldigi token yine aktif oluyor.bunun onune nasil gecebiliriz?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, bu tarz session’ları sizin tracklemeniz gerekmektedir. API stateless olduğu için görevi sadece geçerli bir süreye sahip token üretmektir. Handle işlemini unique bir id kaydedip o id üzerinden siz takip edebilirsiniz, logout olduğunda farklı unique bir değer atamak gibi vb. çözümler düşünebilirsiniz. Aktif olmadığı durumlarda ise zaten token expiry olacaktır.

  25. Şegi dedi ki:

    Eline sağlık panpa sayende owin i kullandım

  26. solugan dedi ki:

    Kardeşim çok teşekkürler paylaşım için bir şey soracağım ben bu işlemi postman da gerçekleştirdim fakat browser da apinin get metodunu çağırdığımda {“Message”:”Authorization has been denied for this request.”} mesajını alıyorum.Bunu webde de getirebilmem için ne yapmam gerekir bir açıklarmısın? Teşekkürler.

  27. onur dedi ki:

    Merhaba Gokhan Bey,

    Hem bu yaziniz hem de refresh token kullanimi yaziniz icin cok tesekkurler. Adeta hayat kurtardiniz

    Iyi Calismalar

  28. Fatih dedi ki:

    Merhaba
    public override async Task GrantResourceOwnerCredentials
    ve
    public override async System.Threading.Tasks.Task ValidateClientAuthentication
    Kısımlarında await kullanılmadığı için altını yeşil olarak çiziyor.
    yoğun kullanıcı kitlesine sahip uygulamalarda sorun yaratırmı?

  29. Alp dedi ki:

    Merhaba Gökhan,

    Bu değerli yazın için çok teşekkürler.

    Android uygulamam için Web API geliştirdim ve Auth sistemini senin bahsettiğin şekilde yaptım.

    Sorun şu ki , Web API’mdeki her metod Auth gerektiriyor ve kullanıcılarım uygulamamı kullanınca bazen Web API çalışmaz hale geliyor…

    Böyle olunca sunucudan IIS ‘ e girip siteyi yeniden başlatıyorum ve sorun düzeliyor…

    Sence bunun çözümü nedir ? Token sistemi IIS ‘ i yoruyor olabilir mi ?

    Uygulamam çalışırken metodlarımda genelde veri tabanımdan 30-50 satırlık veri çekiyor (Uygulama başladığında bunun gibi 3,4 istek yapıyor… , bu isteklerle de alakalı olabilir mi ?)

    İyi çalışmalar…

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhabalar, öncelikle ben teşekkür ederim.

      Sorunuza gelecek olursak eğer API method’larınızın authentication gerektiriyor olmasının ve yük altında “çalışmaz bir hale gelmesi” konusu, ne API ile nede auth işlemleri ile alakalı olduğunu düşünmüyorum. Burada kodlamanızdan kaynaklı bottleneck’leri herhangi bir APM tool’u ile adresleyebilirsiniz. Tahminimce memory leak yaratan bir kod bulunmakta. Ezbere konuşmak zor bu tarz işlemler için.Eğer prod ortamlarınızda newrelic gibi apm tool’ları var ise, bir performans raporu almanızı önerebilirim.

      • Alp dedi ki:

        Tekrardan merhaba Gökhan,

        İlgin için çok teşekkürler.
        Kodlarımın tamamını inceledim ve her bir API çağrımda MySql bağlantısı oluşturduğumu ve sonradan birçoğunun MySql bağlantılarını kapatmadığımı farkettim , tamamen kodları yeniden düzenleyince bi sorun olmadı.

        Dediğin araçları kullanıp temiz bir analiz yapamadım ama çalışıyor şuanlık 😀

        İyi çalışmalar…

  30. Burak dedi ki:

    Merhaba,
    Aşağıdaki kodları tam olarak anlayamadım UserName ve Password ne amaçla kullanılıyor Sqlconnection satırında mssql servera bağlanırken ki gibi tek seferlik bir username ve password mu yoksa benim database serverıma bağlanıp User tablomda ki kullanıcılar mı ?

    if (context.UserName == “Gokhan” && context.Password == “123456”)
    {
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);

    identity.AddClaim(new Claim(“sub”, context.UserName));
    identity.AddClaim(new Claim(“role”, “user”));

    context.Validated(identity);
    }

    Şimdiden Teşekkürler,

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba o kısım kullanıcılarınızın login sırasında token alabilmeleri için gerekli olan standart username, password bilgileridir. Tabi bu kısmı kendinize göre tailor bir business yapabilirsiniz.

  31. Hakan ZOR dedi ki:

    Güzel uygulama olmuş teşekkürler. Şöyle bir problemim var. Benim uygulamamda login olurken 3 ayrı parametre alıyorum. Burada sadece kullanıcı adı ve şifreye göre yapılmış.

    Kullanıcı Adı, Şifre, TC

    Ne yapmam lazım ?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, additional parametreleri “OAuthGrantResourceOwnerCredentialsContext” üzerindeki Request property’sinden erişebilirsiniz. Örneğin:
      var requestForm = await context.Request.ReadFormAsync();
      requestForm[“additionalParameter”] gibi.

      Saygılar.

      • Yunus Emre dedi ki:

        Merhaba,

        Öncelikle faydalı yazınız için çok teşekkür ederim.

        Sistemimde user authentication’a ek olarak, application authentication da olacak. Dolayısı ile username – password ikilisinin yanında clientId (bu zaten context’te mevcut) ve client password’e ihtiyacım olacak.

        Client Password bilgisini yukarıda bahsettiğiniz Additional Parameters’da mı almam mantıklı yoksa başka bir yol mu önerirsiniz application authentication için ?

        • Gökhan Gökalp Gökhan Gökalp dedi ki:

          Merhaba,

          Client doğrulaması için client id ve client secret gibi bilgiler kullanılmakta standart olarak. Validation işlemini ise “ValidateClientAuthentication” method’unda gerçekleştirebilirsiniz.

          • Yunus Emre dedi ki:

            ClientId’yi OAuthGrantResourceOwnerCredentialsContext ve OAuthValidateClientAuthenticationContext nesnelerinin altında görebiliyorum ama Client Secret property’sini göremedim. Onu nereden almak gerekiyor ?

          • Gökhan Gökalp Gökhan Gökalp dedi ki:

            Client secret’a neden ihtiyacınız var?

          • Yunus Emre dedi ki:

            Spesifik olarak Client secret’a ihtiyacım yok aslında. Benim client id ve clientpassword ikilisine ihtiyacım vardı. Client Id zaten context’te mevcut, Header’a da clientpassword’u ben ekleyerek çözmüştüm ama siz client secret yazınca header’a eklediğim clientpassword alanının yerini tutuyor sanıp o yüzden sormuştum. Sanırım yanlış anlamışım kusura bakmayın 🙂

  32. Efe ÖZYER dedi ki:

    Hocam tekrar merhabalar, basic Asp Net Web Api 2 projesi ile bir proje tamamladım ancak bilemediğim bir nedenden dolayı access_token belli kullanıcılarda çok uzun bir string oluyor. Daha sonra token’i header’a ekleyip post ettiğimde ise ;

    HTTP Error 400. The size of the request headers is too long.

    Hatasını alıyorum. Sunucu tarafında bunu çözemedim IIS’de internette geçen tüm ayarları denememe rağmen bu hatayı vermeye devam ediyor. Token uzunluğunu optimize edebilir miyim?

  33. Serkan AYAZ dedi ki:

    Merhaba. Öncelikle kitabınızı okumaya yeni başladım, gerçekten çok güzel bir kaynak. Ben aşağıdaki gibi web servis fonksiyonuna rol tabanlı erişim izni vermek istiyorum. Bunu nasıl yapabilirim?

    [Authorize(Roles = “Admin”)]
    public List List()
    { /*Komutlar*/ }

    Şimdiden teşekkürler.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Selamlar, bu işlemleri claim’ler ile yönetebilirsiniz. Token’ı ürettiğiniz yerde kullanıcının claim’ine rolleri set edebilirsiniz. Kolay gelsin.

      • Serkan AYAZ dedi ki:

        İlginiz için teşekkür ederim. Peki oluşturulan token bilgileri nerede saklanıyor? LoadBalancer’lı bir mimariyi düşündüğümüzde farklı makinalarda oluşturulan tokenları diğer makinalar üzerinde oturum açılmaya çalışıldığında oturum açılır mı? Eğer oturum açılmazsa böyle bir senaryoya nasıl bir çözüm bulunabilir?

        • Gökhan Gökalp Gökhan Gökalp dedi ki:

          Token bilgileri herhangi bir yerde persist edilmiyor. MachineKey bilgileri ile encrypt ediliyor. Load-balancer kısmında bir karışıklık var sanırım. Identity server’ınız lb arkasında ise ve farklı makineler da ise, aynı farmda olabilmeleri ve aynı key’leri üretebilmeleri için machinekey bilgilerinin de aynı olması gerekmektedir. Identity server’ı cluster olarak kurduğunuzda da böyle bir şeye gerekte kalmayacaktır. Eğer identity server yerine custom bir api üzerinden owin context’i ile key’leri siz üretiyorsanız, ozaman ihtiyaç duyacaksınız. Kolay gelsin.

  34. kadir dedi ki:

    Merhaba, adımları uyguladığımda hatta sizin paylaştığınız uygulamayı indirip onda test ettiğimde
    The requested resource does not support http method ‘POST’. hatası alıyorum

  35. kadir dedi ki:

    Merhaba,
    Makalede bahsettiğiniz token alma ve veri çekme ile ilgili yapıları bir c# windows forms uygulamasında kullanılacak şekilde örneklendirebilir misiniz? Yani orderscontroller tarafından sağlanan verilere windows forms ile ulaşmak istiyorum ve aynı zamanda oAuth kullanmak istiyorum.

  36. muhammedakbas dedi ki:

    Gökhan Hocam saygılar,
    tek kelime ile excellent 🙂

  37. Murat dedi ki:

    Merhabalar,

    Çok güzel bir örnek olmuş. Token pat ile ilgili bir sorum olacaktı.
    TokenEndpointPath = new Microsoft.Owin.PathString(“/token”)

    tokenendpoint pathi “/wp/token” şeklinde nasıl tanımlayabiliriz. Yada böyle bir tanımlama yapabilir miyiz.

    Teşekkürler.

  38. Mehmet Ali dedi ki:

    Merhaba makeleniz için teşekkürler. Anlayamadığım bir nokta var. Makelenizde;

    “Authorization Server bu bilgileri doğrulursa, client’a bir Access Token Http Response’u döner.” ve
    “Client artık erişmek istediği servislere, elde etmiş olduğu Access Token’ı Http Request’in Authorization Header‘ına ekleyerek erişim sağlar.” diye yazmışsınız.

    Toke’nin Headera eklenmesiyle yapılan isteklerde, sistem temel olarak token doğrulamasını nasıl yapıyor? Yani, oluşturularak Clienta göndereilen Token aynı zamanda server tarafında tutuluyor mu? Tutuluyorsa hangi logic ile? Cache mi database mi?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba tutulma işlemi bulunmamakta. Her şey on the fly olarak gerçekleşiyor. Token alınırken veriler encrypt ediliyor, daha sonrasında ise decrypt işlemi gerçekleşiyor ve bu işlem sırasında da expire time’ları da göz önünde bulunduruluyor. Token ile gelinen endpoint üzerinde owin kurulu ise kendisi bu pipeline’ı otomatik olarak işletiyor.

      Saygılarımla.

  39. İlker Yüksel dedi ki:

    Merhaba,
    Çok bilgilendirici bir yazı olmuş teşekkür ederim.
    Biraz temel kısımda takılmış olabilirim ama şu kavramlarda sanırım bir sıkıntım var. Bildiğim kadarıyla;
    Authentication : Kullanıcının siteme giriş yapmasını kontrol eden sistem
    Authorization : Giriş yapmış kullanıcının ilgili işleme erişimini kontrol eden sistem
    Yazı başlığında ve konusunda authentication işlenmesine rağmen neden Authorize attribute’ü kullandık ?

    Aşağıdaki makalede Authorize attribute’ünü Authorization kısmında kullanmışlar bu yüzden biraz karıştırdım sanırım
    https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba evet kavramlar doğru. Attribute konusuna gelirsek, authentication client’ın makinaya erişmesine bakarken, authorization ise ilgili kullanıcının gerçekleştirmek istediği request’e izni var mı yok mu gibi konulara bakmaktadır. Pipeline’a baktığınızda ise, en son AuthorizationFilter’lar gelmektedir. Burada ise ilgili scope ve claim’ler doğrultusunda kullanıcılara işlem yaptırılabilmektedir. Bu sebeple en authorize attribute’ü kullanılmaktadır.

  40. Ali dedi ki:

    merhaba,

    token üretirken grant_type = password yerine grant_type = client_credentials olarak token üretmek istersem ne yapmam gerekiyor ?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, herhangi bir şey yapmanıza gerek yoktur. Client credentials flow’u ile ilerlemek istiyorsanız grant_type’ı set edip, client id ve client secret ile devam etmelisiniz.

  41. golbasi dedi ki:

    hocam kolay gelsin, kafama şey takıldı, şimdi sunucu tarafında üretilen token keyleri, acaba sunucuda bir yerde depolanıyor mu, zira token kullanarak istek geldiğinde karşılaştırmayı nasıl yapacak?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, depolanmamaktadır tüm işlemler on the fly olarak hesaplanmaktadır. Bunu daha önceki yorumlarda cevaplamıştım. Token’lar machineKey’e göre encrypt ve decrypt edilmektedir.

  42. hikmet dedi ki:

    Merhaba,

    Token’ı tek kullanlık nasıl yapabiliriz ? Yani oluşturulan her token yalnızca 1 kere kullanılabilsin. Her method çağrıldığında farklı token istesin

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba neden böyle bir şeye ihtiyacınız var? Token’ın kullanım amacı bu şekilde olmamalı OAuth çatısı altında. Eğer method based credentials’a ihtiyacınız varsa da, bunları scope’lar ve claim’ler ile yönetebiliyor olmalısınız. Saygılar.

  43. Arda dedi ki:

    Hocam saygılar. Bir mobil projem var, verileri servisten çekiyorum. Ben token olayını şu şekilde yaptım. Client servise kullanıcı adı parola ile geliyor, bilgiler doğruysa o kulanıcıya token olarak guid atıyorum ve sqlservere kaydediyorum(atadığım bu tokeni cliente result ediyorum oda kendi hafızasına alıyor.). Daha sonra client sorgulama ekranına gelip sorgulama parametrelerinin yanında birde tokeni yolluyor. servis bu tokene sqlserverdan bakıp geçerli oturum olup olmadığına bakıyor oturum geçerliyse sorgulama sonucunu döndürüyor. doğru değil veya süresi dolmuşsa hata dönderiyirum. ben sistemimi bu şekilde kurdum. Sizin bu anlattığınız sisteme geçsem mi diye düşünüyorum. Sizce geçmelimiyim. Benim sistemimden farkı daha güvenlikli olmasımı yoksa benim sistemimde aynı işi yapıyor mu?

    • Arda dedi ki:

      Birde ben kendi sistemimde: kullanıcı bir kere girip token aldıktan sonra sistemden çıkıp tekrar girerse veya başka bir cihazdan oturum açarsa eski oturumu iptal ediyorum. bunu bu sistemde şöyle yapmayı düşündüm:
      /token den kullanıcıya tokeni return ettim aynı zamandada sqlserverde log tabloma bu tokeni kaydettim. daha sonraki girişlerde aynı kullanıcı tekrar girerse eski oturmu iptal edeceğim.

      sizce mantıklımı?

      • Gökhan Gökalp Gökhan Gökalp dedi ki:

        OAuth standartlarında bu tarz bir işlem yapabilmek standart dışı olarak ancak, custom bir şekilde gerçekleştirebilirsiniz. OAuth için token’ın bir expire date’i vardır ve expire date’i geldiğinde sona erer. Eğer business’ınız bunu gerektiriyorsa tek bir oturumu, custom olarak gerçekleştirmelisiniz.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, token’ları persist etmeniz çok efektif olmayacaktır. OAuth 2.0 standartlarında token’ları bearer olarak on the fly yapmanız sizin yararınıza olacaktır. Saygılar

  44. Hikmet dedi ki:

    Merhaba, Token dönerken yanında farklı bir bilgi daha döndermek istiyorum(örn kullanıcıId) nasıl dönderebilirim.

  45. Hikmet dedi ki:

    identity.AddClaim(new Claim(“UserId”, “12345”));

    olarak eklesem bile Json dönüşünde sadece access_token,expires_in ve “bearer” bilgileri görüüyorum. Burada UserId ninde dönmesini istiyorum. Nasıl yapabilirim?

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, claim üzerine set ettiğiniz bilgileri ilgili client üzerinden kullanıcı validate olduktan sonra, System.Web.Http namespace’i altında bulunan User context’i üzerinden ulaşabilirsin. Saygılar.

  46. ahmet dedi ki:

    Gökhan merhaba, Yazdığım bir api servisine hangi domainlerden istek geldiğini nasıl görebilirim.
    Amacım api’i kullanan siteleri tespit etmek. ajax ile gelen isteklerde Request.UrlReferrer den görebiliyorum ama mesela Asp.Net Mvc de backend den httpclient ile yaptığım bir istekte UrlReferrer değeri boş geliyor.

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, eğer null’sa yapılabilecek bir şey var mı bilemiyorum. Eğer probleminiz farklı domain’lerden api’ınızın call edilmesi ise, cors ayarlarını yapmanızı tavsiye ederim. Bir diğer çözüm ise urlreferrer kontrolü yapmanız olacaktır null mı değil mi gibi. Kolay gelsin.

  47. metin dedi ki:

    Merhaba, öncelikle authentication konusundaki aydınlatıcı fikirleriniz için teşekürler.
    Ben örnek projenizi indirip postman tool ile sıkıntısız işlemler yaptım.
    Yardım istediğim konu postman(bir metoda authenticate olup ticket alma sonra bu token ile başka metod çağırma) ile yaptığımız işlemleri asmx web serviste backened olarak nasıl yapabilirim. Biraz denedim ama işin içinde çıkamadım.
    token ile asmx web servisi authentication örnek bir kod gösterebilir misiniz
    Teşekürler..
    Saygılarımla

  48. mamacita dedi ki:

    Her şeyi teker teker ve sade bir dille açıklamışsınız, teşekkürler.

  49. Mustafa Bardakci dedi ki:

    Merhaba, öncelikle makale için teşekkür ederim. Güzel olmuş. Ajax post ile token alma konusunda sıkıntı yaşamıyorum fakat ajax post güvenli gelmediği için post işlemini controller içerisinden yapmaya çalıştığımda bir türlü context parametrelerini geçemedim.

    https://i.hizliresim.com/ZZ8YX0.jpg

  50. Onur dedi ki:

    Anlatım gayet güzel olmuş eline sağlık. Kurulumu yaptım web api uygulamam için postman üzerinden testini gerçekleştirdiğimde token alma ve bu token ile request gönderme işlemleri başarıyla çalıştı. Ancak tek bir problemim var jquery ajax ile token almak için post işlemi gerçekleştirdiğimde 404 (Not Found) ve No ‘Access-Control-Allow-Origin’ header is present on the requested resource. hataları alıyorum. Web api çağırılarımda da aynı hatayı alıyordum httpResponseMessage.Headers.Add(“Access-Control-Allow-Origin”, “*”); ekleyerek çözmüştüm. Ancak oauth ‘da bu yeterli olmadı. Çözüm için öneriniz var mı.

  51. Ayşe Sayarı dedi ki:

    Merhabalar, örneklendirmeleriniz ve makaleniz için çok teşekkür ederiz. Gerçekten çok makbule geçti ve fayda gördüm. Yalnız bir konuda size danışmam gerekti. Örneğinizde bahsettiğiniz yetkilendirmeleri yaparken metod başına [Autorize] özniteliğini yerleştiriyorsunuz.

    Ben simple membership kullanmıyorum ve kendi üyelik sistemim var. Metodun başına koyduğunuz [Authorize] özniteliği membership için mi yoksa OAuth 2.0 nin bir parçası mı, açıkçası tereddütte kaldım.

    Bu konuda bir fikriniz var mıdır ? Hazır membership kullanmıyorsak, OAuth 2.0 yi implement edebiliyor muyuz projemize ?

    Teşekkürlerimi sunarım.

    Ayşe

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, Authorize attribute’ü “System.Web.Http” içerisinden gelmektedir. Ister OWIN ile OAuth imp. kullanabilirsiniz, isterseniz de eğer simple membership provider kullanıyorsanız onunlada kullanabilirsiniz. Teşekkür ederim.

  52. Emre dedi ki:

    Merhaba , username password e ek olarak bir parametre daha göndermek istiyorum acaba ne yapmam gerekli anlatım için teşekkürler

    • Gökhan Gökalp Gökhan Gökalp dedi ki:

      Merhaba, additional parametreleri “OAuthGrantResourceOwnerCredentialsContext” üzerindeki Request property’sinden erişebilirsiniz. Örneğin:
      var requestForm = await context.Request.ReadFormAsync();
      requestForm[“additionalParameter”] gibi.

      Saygılar.

Bir Cevap Yazın

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

*