Asp.NET MVC – Web Api Token Authentication
Bir önceki Asp.NET MVC – Web Api Nedir? Nasıl Oluşturulur? başlıklı yazımda Web Apilerin ne olduklarına ve nasıl oluşturulduklarına değinen içeriği kaleme(klavyeye) almıştık. Bu içeriğimizde ise oluşturduğumuz Web Apilerde Token Authentication ile kullanıcı taraflı doğrulama uygulamasını inceliyor olacağız.
Token Authentication Nedir?
“Token” kelimesi Türkçe’de “jeton”, “işaret”, “anahtar” vs. şeklinde karşılığı olan bir kelimedir. Ben burada “jeton” tabirini tercih etmekteyim.
Token Authentication; oluşturduğumuz Web API’yi kullanmak isteyenlere karşı, geliştiriciler tarafından kontrol ve güvenlik mekanizması sağlayan bir doğrulama yöntemidir. API geliştiricisi, token authentication yöntemini kullanarak Apiyi kullanmak isteyen clientlara denetleme sağlamakta ve bu şekilde kontrollü bir açılım uygulamaktadır. Denetlemede doğru kullanıcı adı ve şifreyi giren kullanıcıya server tarafında belirli bir süreliğine bir adet token oluşturulur. Kullanıcı bu tokenı kullanarak Web API’nin nimetlerinden faydalanabilmektedir.
Token Authentication İçin Hangi Kütüphanelerin Projeye Entegrasyonu Gereklidir?
Token Authentication’ı sağlayabilmek için aşağıdaki kütüphanelerin projeye entegre edilmesi gerekmektedir;
- Microsoft.AspNet.WebApi.Owin
- Microsoft.Owin.Security.OAuth
- Microsoft.Owin.Cors
- Microsoft.Owin.Host.SystemWeb
İlgili kütüphanelerin entegrasyonunu “NuGet Package Manager” penceresinden sağlayabilirsiniz.
Token Authentication’ın Uygulanması
Şimdi varsayalım ki elimizde aşağıdaki Web API Controller bulunsun.
public class PersonelController : ApiController { NorthwindEntities db = new NorthwindEntities(); public IEnumerable<Personel> GetAllPersonel() => db.Personeller.Select(p => new Personel { Adi = p.Adi, Soyadi = p.SoyAdi, Unvan = p.Unvan }); public Personel GetPersonel(int id) => db.Personeller.FirstOrDefault(p => p.PersonelID == id); public IHttpActionResult PostPersonel(Personel personel) { db.Personeller.Add(personel); db.SaveChanges(); return Ok(personel); } }
Bu apiye özel bir Token Authentication oluşturalım.
İlk olarak projeye “Startup.cs” dosyası ekleyelim.
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration httpConfiguration = new HttpConfiguration(); ConfigureOAuth(app); WebApiConfig.Register(httpConfiguration); app.UseWebApi(httpConfiguration); } void ConfigureOAuth(IAppBuilder app) { //Token üretimi için authorization ayarlarını belirliyoruz. OAuthAuthorizationServerOptions oAuthAuthorizationServerOptions = new OAuthAuthorizationServerOptions() { TokenEndpointPath = new PathString("/token"), //Token talebini yapacağımız dizin AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), //Oluşturulacak tokenı bir gün geçerli olacak şekilde ayarlıyoruz. AllowInsecureHttp = true, //Güvensiz http portuna izin veriyoruz. Provider = new ProviderAuthorization() //Sağlayıcı sınıfını belirtiyoruz. Birazdan bu sınıfı oluşturacağız. }; //Yukarıda belirlemiş olduğumuz authorization ayarlarında çalışması için server'a ilgili OAuthAuthorizationServerOptions tipindeki nesneyi gönderiyoruz. app.UseOAuthAuthorizationServer(oAuthAuthorizationServerOptions); //Authentication Type olarak Bearer Authentication'ı kullanacağımızı belirtiyoruz. app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); //Bearer Token, OAuth 2.0 ile gelen standartlaşmış bir token türüdür. //Herhangi bir kriptolu veriye ihtiyaç duyulmaksızın client tarafından token isteğinde bulunulur ve server belirli bir zamana sahip access_token üretir. //Bearer Token SSL güvenliğine dayanır. } }
Yukarıdaki “Startup.cs” sınıfını incelerseniz eğer “Configuration” metodunda gerekli http konfigürasyonları sağlanmaktadır. “ConfigureOAuth” isimli metotta ise token üretimi için gerekli authorization oluşturulmakta ve gerekli provider sınıfı tanımlanmaktadır.
Tanımladığımız “ProviderAuthorization” isimli provider sınıfımızıda incelersek eğer;
public class ProviderAuthorization : OAuthAuthorizationServerProvider { public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { //Domainler arası etkileşim ve kaynak paylaşımını sağlayan ve bir domainin bir başka domainin kaynağını kullanmasını sağlayan CORS ayarlarını set ediyoruz. context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); //Kullanıcının access_token alabilmesi için gerekli validation işlemlerini yapıyoruz. if (context.UserName == "Gençay" && context.Password == "SebepsizBoşYereAyrılacaksan") { ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim("sub", context.UserName)); identity.AddClaim(new Claim("role", "user")); context.Validated(identity); } else { context.SetError("hata", "Kullanıcı adı veya şifre hatalı."); } } }
Yukarıdaki kod bloğunu incelerseniz eğer, oluşturmuş olduğumuz ProviderAuthorization sınıfının client erişimine izin verebilmek için ValidateClientAuthentication metodunu OAuthAuthorizationServerProvider sınıfından override ettik. Benzer şekilde ProviderAuthorization sınıfının kaynak erişimine izin verebilmek için de GrantResourceOwnerCredentials metodunu override etmiş bulunmaktayız.
Artık Token Authentication için gerekli tüm çalışmaları gerçekleştirmiş bulunmaktayız. Dolayısıyla ilgili Web Apimizde doğrulama güvenliği uygulamak istediğimiz metotları “Authorize” attribute’u ile işaretlememiz yeterlidir. Tabi ben tüm metotlarımda bu doğrulamayı istediğim için komple web api sınıfını ilgili attribute ile işaretlemekteyim.
[Authorize] public class PersonelController : ApiController { NorthwindEntities db = new NorthwindEntities(); public IEnumerable<Personel> GetAllPersonel() => db.Personeller.Select(p => new Personel { Adi = p.Adi, Soyadi = p.SoyAdi, Unvan = p.Unvan }); public Personel GetPersonel(int id) => db.Personeller.FirstOrDefault(p => p.PersonelID == id); public IHttpActionResult PostPersonel(Personel personel) { db.Personeller.Add(personel); db.SaveChanges(); return Ok(personel); } }
Evet… Şu noktadan itibaren Postman uygulaması üzerinden herhangi bir GET ya da POST metoduna requestte bulunduğumuzda aşağıdaki hatayla karşılaşacağız.
{
“Message”: “Authorization has been denied for this request.”
}
Gördüğünüz üzere web apimiz token üretmeyen kullanıcılara nimetlerini sunmamaktadır.
Öncelikle token üretmemiz gerekecektir. Haliyle ilk olarak aşağıdaki linki belirtilen headers ve body özellikleriyle tetikleyerek gerekli kullanıcı adı ve şifre ile tokenımızı elde edelim.
http://localhost:*****/token
Headers’a eklenecek parametreler;
Header | Value |
---|---|
Accept | application/json |
Content-Type | application/x-www-form-urlencoded |
Body’e eklenecek parametreler;
Key | Value |
---|---|
grant_type | password |
username | Gençay |
password | SebepsizBoşYereAyrılacaksan |
Görüldüğü üzere tokenımızı elde etmiş olduk. Artık bu tokenı kullanarak Web Api’de istediğimiz herhangi bir metoda erişebiliriz.
GET ya da POST metotlarına erişmeye çalışırken her ikisinde de ortak olan headers özelliklerini aşağıdaki gibi vermemiz yeterli olacaktır.
Header | Value |
---|---|
Content-Type | application/json |
Authorization | Bearer (….D4buSqsfoyuXEdvWpvpBGbHBTP9FAY…) |
Burada dikkat etmeniz gereken nokta, Authorization’a token değerini yazarken başına “Bearer” değerini yazmayı unutmayınız.
Görüldüğü üzere web api’de ki her bir metot için elde ettiğimiz token ile başarılı requestlerimizi gerçekleştirmiş bulunmaktayız.
Bu satırlardan itibaren Asp.NET MVC – Web Api uygulamalarında Token Authentication’ın nasıl sağlandığını yeterince incelemiş bulunuyoruz. Umarım faydalı bir içerik olmuştur.
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…
Emeğinize sağlık..
İşlemleri Wep Api projeme uygulayıp çalıştırıdığımda aşağıdaki hatayı almaktayım. Bu konu ile ilgili yardımcı olabilir misiniz?
The following errors occurred while attempting to load the app.
– No assembly found containing an OwinStartupAttribute.
– No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of “false” in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
Merhaba,
Şu makalemi inceleyebilirsin 🙂
merhabalar,
mvc projemin view bölümüne taşımak isterim yani postman olmadan kullanıcı bilgileri girebileceği bir login page ile nasıl entegre edebilirim.
teşekkürler.
allah aşkına mvc kullanılarak jwt ile authentication ve authorization nasıl yapılır bilen varmı.
Merhaba,
Asp.NET Core 3.1 ile Token Bazlı Kimlik Doğrulaması ve Refresh Token Kullanımı(JWT) başlıklı makalemi okumanızı ve Asp.NET Core + Angular eğitim serimizdeki 40 ile 47. eğitimlerime göz atmanızı tavsiye ederim.
Kolaylıklar dilerim…
Abi Allah razı olsun bu konu günlerdir kafama takılıyordu, bir de E ticaret uygulamasında angular bilmeden mvc üzerinden uygulamayı paralel şekilde ilerletebilir miyim?
Merhaba Ömer,
İşini görmene sevindim.
Yapabilirsin tabi, genel mantığın dışında nerede çalışıyorsan oraya göre ihtiyaçları belirler ve işlevi gerçekleştirebilirsin.
Kolay gelsin.
Tesekkurler
Şifreyi SebepsizBoşYereAyrılacaksan olarak gördüm sadece ölüler görür… bir sigara yaktım
Merhaba,
Uzun süredir owin kütüphanesini kullanarak TOKEN işlemlerini yapıyorum. Oluşan TOKEN’lara nasıl erişebiliriz? Senaryo: Admin aktif kullanıcı listesine giriş yapar ve karşısına aktif kullanıcı listesi gelir, kullanıcı listesinde seçili kullanıcıyı sistemden atabilir. Bu senaryoyu yapabilmem için bana 2 ayrı metot lazım;1. metot aktif token listesini verebilecek, 2. metot token id si verilecek veya başka bir değer alıp signout yaptırması gerek. Bazı kaynaklara baktım çözüm bulamadım, siz sürekli projeler geliştirdiğinizden illa ki bu senrayoya benzer iş yapmışsınızdır diye sormak istedim. Yardımcı olursanız çok sevinirim.
kısmını yazdığımda derleme hatası alıyorum. .net 7.0 ile çalışıyorum. yardımcı olabilir misiniz ?
merhaba yanlışım varsa düzeltin heryerde server side tarafında login bilgilerileri şifreleyip db ye yazmayı göstermişler.Oysaki site https değilse browser üzerindeki header da giriş bilgileri elde ediliyor bunun için aynı wifi ağındaki browser ların header larını fiddler tarzı bir programla ele geçirebilinir.Bu yüzden bana göre client side tarafında bunların şifrelenmesi ve server bu şekilde gönderilmesi.Yazınız güzel olmuş
Bilgi için teşekkürler.