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…