Merhaba,
Bu içeriğimizde, Amazon Cognito ile .NET WebAPI’ın güvenliğini sağlama konusunda kapsamlı bir inceleme çalışması gerçekleştiriyor olacağız. Odak noktamız, OAUth ve Amazon Cognito eşliğinde Serverless Authentication sistemi oluşturabilme üzerine olacaktır. Bu içeriğin sonunda .NET WebAPI’larınızın güvence altına almak için Amazon Cognito’yu nasıl uygulayacağınızı tam teferruatlı anlamış olacaksınız kanaatindeyim. O halde vakit kaybetmeksizin buyurun başlayalım…
Amazon Cognito Nedir?
Geliştirilen uygulamanın ölçeği ne olursa olsun kimlik doğrulama her daim önem arz edecek olan kritik ihtiyaçlardan birisidir. Bu ihtiyacı ister kendi özel oluşturduğunuz kimlik doğrulama stratejisi ile isterseniz de third party provider’lar ile sağlayabilir ve kullanabilirsiniz. Ya da isterseniz de AWS tarafından sağlanan kullanıcı kimlik ve yönetim hizmeti olan Amazon Cognito’yu da tercih edebilirsiniz.
Amazon Cognito; kimlik doğrulama, kullanıcı yönetimi ve veri senkronizasyonu gibi özellikleri sağlayarak uygulamaların geliştirme süreçlerinde pratikleştirici bir nitelik sağlamaktadır.
Amazon Cognito ile özellikle mobil ve web uygulamaları gibi farklı platformlarda kullanıcıların kimliklerini doğrulamak için OAuth 2.0, OpenID Connect veya SAML vs. gibi standart kimlik sağlayıcıları ile entegre olunabilmektedir. Böylece .NET geliştiricileri olarak kendi kimlik doğrulama sistemimizi OpenIddict veya IdentityServer4 gibi kütüphaneleri kullanarak geliştirmek yerine(ki bunlar hala geçerli yaklaşımlardır), Amazon Cognito servisiyle oldukça avantajlı ve efektif bir şekilde kurgulayabiliriz.
Böylece;
- Amazon Cognito’nun sağlayacağı akıcı bir kullanıcı arayüzü üzerinden nispeten kolay bir kullanıcı yönetimi ve oturum işlemleri gerçekleştirilebilecek ve Facebook, Google vs. gibi harici identity provider’lar da basit ama etkili bir şekilde desteklenebilecektir.
- Herhangi bir altyapı ihtiyacına dair endişeye gerek kalmaksızın; Amazon Cognito, istenilen sayıda kullanıcıya uyum sağlayacak şekilde ölçeklenebilecektir.
- Özelleştirilmiş kimlik doğrulama sitemi tasarlarken, potansiyel hataların ve açıkların oluşma olasılığı oldukça düşük olacak ve böylece birinci sınıf güvenlik sağlanacaktır.
- Diğer AWS servisleriyle olan entegrasyon kolayca yürütülebilecektir.
- Ve son olarak tüm bu özellikler aylık 50.000 aktif kullanıcıya ve external identity provider açısından da 50 kullanıcının oturum açmasına kadar ücretsiz olarak kullanılabilecektir. Ha eğer ki bu sınırların aşılması gerekiyorsa bunun da oldukça makul fiyat politikasıyla gerçekleştirilmesi mümkündür. https://aws.amazon.com/tr/cognito/pricing/
Ne İnşa Edeceğiz?
Amazon Cognito’yu kullanarak serverless bir authentication sistemi tarafından güvenliği sağlanan Web API geliştireceğiz. Bu API’daki authentication, Amazon Cognito User Pool tarafından oluşturulan JWT’ye dayanacaktır.
Bunun için ilk olarak Cognito’da client credentials ve password flow ayarlamalarını gerçekleştirecek ve daha sonra da bu akışların bize belirli bir kullanıcı için token üretebilme yeteneğini test edeceğiz. Bu işlem tamamlandığında, Amazon Cognito tarafından güvenli hale getirilen API’ı oluşturacak ve bu API’ın her iki akıştan gelen token’ları alabildiğini ve güvenli bir API endpoint’ine yapılan request’leri doğrulayabildiğini kontrol edeceğiz.
Client Credential Flow & Password Grant Flow
Client Credential Flow’da client(yani geliştireceğimiz Web API), access token karşılığında Cognito’ya client id ve secret değerlerini iletecek ve herhangi bir kullanıcı onayına ihtiyaç duymaksızın client yetkilendirilecektir.
Password Grant Flow ise kullanıcının kaynaklarına erişmek için bir server authentication yapılması gerekmektedir. Dolayısıyla bu noktada kullanıcı adı ve şifre gibi kullanıcı bilgilerinin gönderilmesi elzemdir.
Amazon Cognito User Pool Oluşturma
Şimdi ilk olarak Amazon Cognito User Pool oluşturmaya odaklanalım. Bunun için AWS’ye giriş yapalım ve AWS Console üzerinden Cognito’yu aratalım.
Client Credentials Flow: Kurulum ve Test
Şimdi bu oluşturduğumuz user pool client’ında client credentials flow’u uygulayacağız. Zaten güvenlik nedenleriyle aynı user pool client’ında birden fazla flow uygulanamamaktadır. Bu nedenle içeriğimizin sonraki satırlarında password grant flow’u uygularken de bunun için yeni bir client oluşturuyor olacağız.
Client credential flow’un temel fikri; client’ın kullanıcı kimlik bilgileri yerine, client id ve client secret gibi kendisine ait kimlik bilgileri eşliğinde Amazon Cognito’dan authentication yapması üzerine kuruludur. Bu akış genellikle protected edilmiş resource’lara erişimi sağlayabilmek için sadece client’ın yetkilendirilmesinin yeterli olduğu senaryolarda tercih edilmektedir. Bizlerde bu senaryoya benzer bir çalışma yapacağımızdan dolayı erişim açısından örneklendirmeyi sağlayabilmek için bir resource server’a ihtiyacımız söz konusudur.
Bunun için yukarıdaki satırlarda oluşturduğumuz ‘cognito-example’ isimli user pool’a girelim ve aşağıdaki ekran görüntüsünde olduğu gibi ‘App integration’ sekmesi üzerinden ‘Resource servers’ alanında ‘Create resource server’ butonuna tıklayalım.
JWT oluşturabilmek için aşağıdaki url’e verilen parametreler eşliğinde bir POST request’i göndermemiz yeterlidir.
https://{domain}.auth.{region}.amazoncognito.com/oauth2/token
Buradaki domain ve region bilgilerini peşinen elde etmek için oluşturulan user pool’un ‘App integration’ sekmesi altındaki ‘Domain’ başlığına göz atabilirsiniz.
İçeriğimizin bu noktasına kadar client credential flow’a odaklı çalışıp, test amaçlı bir doğrulama gerçekleştirmiş bulunuyoruz. Bir sonraki adımda password grant flow’a odaklanacak ve kullanıcı adı ile birlikte şifresini kullanacağımız çalışmaları gerçekleştireceğiz.
Password Grant Flow: Kurulum ve Test
Şimdi de password grant flow authentication için başka bir application client oluşturmamız gerekmektedir. Bunun için aşağıdaki ekran görüntüsünde olduğu gibi ‘cognito-example’ isminde oluşturduğumuz user pool üzerinden ‘App integration’ sekmesine gelelim, oradan da sayfanın biraz aşağısındaki ‘App client list’ kısmından ‘Create app client’ butonuna tıklayarak yeni client oluşturma sayfasına gelelim.ALLOW_USER_PASSWORD_AUTH değerini seçelim. Bunun dışında aşağıdaki ekran görüntüsünde olduğu gibi oluşturulacak token’a dair expiration değerlerini kendinize ya da iş kurallarınıza göre belirleyebilirsiniz. Biz varsayılan değerlere bağlı kalarak yola devam edelim.
Hazır lafı geçmişken buradan Şuayip abiye de selamlar olsun🤚🥸
Ha tabi burada girilen şifrenin geçici olduğunu da unutmamak lazım.
aws cognito-idp admin-set-user-password --user-pool-id "<user-pool-id>" --username "<username>" --password "<permanent-password>" --permanent
Bizler misal olarak, bu talimatı aşağıdaki gibi kullanalım;
aws cognito-idp admin-set-user-password --user-pool-id "us-east-1_Vol2qyQFn" --username "şuayip" --password "1q2w3E4'" --permanent
Bu işlem tamamlandıktan sonra eklediğimiz kullanıcının onaylanmış olduğunu göreceksiniz.
Biliyorsunuz ki, password grant flow’da user credentials bilgilerinin sunucuya iletilmesi gerekmektedir. Bunun için de OAuth 2.0 protokolü kapsamında gerçekleşecek olan yetkilendirme işlemlerini destekleyecek header’lar eşliğinde request’te bulunmamız gerekmektedir. Haliyle https://cognito-idp.{region}.amazonaws.com/ adresine aşağıdaki ayarlarda bir POST isteğinde bulunulması gerekmektedir.application/x-amz-json-1.1 değerini veriyoruz. Böylece AWS Cognito Identity Provider API’ıyla kuracağımız iletişimde göndereceğimiz kullanıcı adı ve şifre gibi verilerin biçimini ifade etmiş oluyoruz.
‘X-Amz-Target’ başlığına karşılık ise AWSCognitoIdentityProviderService.InitiateAuth değerini veriyoruz. Böylece yapılacak request’in hangi AWS servisine gideceğini ifade etmiş oluyoruz. Bu header’lar eşliğinde request’in body’sini de aşağıdaki gibi ayarlayalım.
Şimdi içeriğimizin seyri açısından client credential flow ve password grant flow’u incelediğimize göre geriye, serverless authentication işlemini kullanarak tarafımızca oluşturulmuş olan bir Asp.NET Core Web API uygulamasının güvenliğini sağlamak kalmıştır.
Amazon Cognito İle Web API’ın Güvenliğini Sağlama
İlk olarak bir Asp.NET Core Web API projesi oluşturalım ve ardından ilgili projeye aşağıdaki kütüphaneleri yükleyelim.
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCognitoIdentity();
builder.Services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// https://cognito-idp.{region}.amazonaws.com/{user-pool-id}
options.Authority = "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Vol2qyQFn";
options.TokenValidationParameters = new()
{
ValidateIssuerSigningKey = true,
ValidateAudience = false
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", [Authorize] () =>
{
return Results.Ok(true);
});
app.Run();
Yukarıdaki kod bloğuna göz atarsanız eğer; 6. satırda AddCognitoIdentity metodu ile uygulamanın authentication ve authorization süreçleri Cognito API’larına göre yapılandırılmakta ve 8 ile 23. satır aralığında ise JWT bearer authentication’a göre şemalar ayarlanmakta ve özellikle authorization server olarakta 17. satırda Cognito belirlenmektedir. 32 ve 35. satır aralığında ise authorize edilerek oluşturulmuş olan bir minimal api mevcuttur.
Şimdi bizler bu API’a direkt bir istekte bulunursak aşağıdaki görselden de anlaşılacağı üzere 401 Unauthorized durumuyla karşılaşacağız.Bearer .... şeklinde verirsek aşağıdaki görselde olduğu gibi isteğin başarıyla gerçekleştirildiğini görmüş oluyoruz.
Geliştirdiğimiz yazılım sistemlerinde kritik noktalardan biri olan authentication ve authorization yapılanmalarını kâh yazılım dahilinde geliştirebilir, kâh merkezi bir authorization server kurmamızı sağlayan OpenIddict veya IdentityServer4 gibi hazır kütüphaneler eşliğinde inşa edebiliriz. Tüm bunların dışında cloud tabanlı olan AWS Cognito sayesinde hem authentication ve authorization sorumluluklarını yapılandırabileceğimiz gibi hem de kullanıcı yönetimi ve Facebook, Google vs. gibi sosyal kimlik sağlayıcılarıyla entegrasyon gibi çeşitli yetenekleri de kolaylıkla gerçekleştirebiliriz. Tercih; önce gereksinimlerin, sonra sizin 🙂
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
Not : Örnek çalışmayı aşağıdaki github adresinden edinebilirsiniz.
https://github.com/gncyyldz/Amazon.Cognito.Example
