.Net Core Mikroservis Mimarisinde IdentityServer4 Framework’ü (Pratik -2)

MEHMET ZEKİ KARA
Innovile
Published in
7 min readMay 29, 2021

Geçen yazıda bu yazının birinci serisini yazmıştık. O yazıyı henüz okumayanlar bu adresten yazıya ulaşabilirler.

Not: Bu yazımın sonunda beraber yazacağımız projenin Github linkini sizler ile paylaşıyor olacağım :))

Hadi Asp.net Core 3.1 ile Identityserver4 implementasyonunu beraber gerçekleştirelim.

Microservice mimarisinde geliştireceğimiz bir projemiz olsun. Bu projede;

  • Client1 ve Client2 adında 2 adet Web Application projesi,
  • API1 ve API2 adında 2 adet API projesi ve
  • AuthServer adında bir Identity projemiz mevcut olsun.

AuthServer projesini Web Application (MVC) olarak oluşturacağız. Ancak bu bizim için hem bir API uygulaması hem de bir Client uygulaması görevi sağlayacaktır.

Öncelikle projelerimizin ayağa kaldırılacağı portları belirtelim. Bunun için projemizde “Properties” klasörünün altındaki “launchSettings.json” a gitmemiz gerekiyor.

Yukarıda API1 projesi için örnek gösterilmiştir. Tüm projeler için port numaraları şu şekilde olacaktır:

AuthServer -> https://localhost:5001

Client1 => https://localhost:5006

Client2 => https://localhost:5011;

API1 => https://localhost:5016;

API2 => https://localhost:5021;

IdentityServer4 Framework’ünün anlaşılması kritik olduğu için kodlama ile beraber biraz teorik olarak da anlatıyor olacağım.

Şimdi yemektarifi.com adında bir sitemiz olsun diyelim. Bu sitede ilgili yemek tarifelerine erişmek için herhangi bir Register-Login işlemi gerekmiyor. İlgili URL’e gittiğimizde karşımıza tüm yemek tarifeleri listeleniyor olacak.

Yemek tarifi projemizde web ve mobil uygulamalarımız geliştirdiğimiz API’lerden besleniyor olacak. Burada AuthServer ile API’lerimizi koruma altına almamız gerekiyor ki başkaları da yani başka clientler de bu API’lere erişemez olsun. Bu API’lerden data alabilmek için mutlaka bir Acces Token göndermemiz lazım.

Şimdi bizim burada AuthServer projesine hem API’leri hemde Client’leri tanıtmamız lazım. Ardından hangi Client’ların hangi API’lere erişebileceği hatta hangi metotlara izni olacağı (İnsert, Update, Delete, Get gibi) bilgisini vermemiz gerekiyor. Yukarıdaki görselde de belirtiğim gibi. Web 1 uygulaması sadece API1 ve API2 ye erişebiliyor, Web 2 uygulaması da sadece API2 ve API3 ye erişebiliyor.

Peki bu işlemler nasıl gerçekleşecek?

Burada AuthServer Clientlar için ClientId ve ClientSecret adında iki tane alan tanımlıyor. Bunları kullanıcı adı ve şifre gibi düşünebilirsiniz. Ama bunlar normal kullanıcı değil client bilgisi. Sonuçta hangi clientın istek yaptığını bu bilgilerden tanıyor olacak.

Kısacası burada Web uygulaması kendi CliendId ve Clientd Secret bilgisi ile AuthServer servisine bir istek atacak AuthServer ilgili clientlere bir Token gönderecek ve clientlar artık bu token ile API’lere istek atabiliyor olacak.

Burada API’lerde de ek bir kodlama yapıyor olacağız. Yani isteği atan token kimin tarafından atıldı? , gerçek bir token mı? Onun kontrolünü yapıyor olacağız.

OAuth2.0 protokolünde 4 adet izin tipleri vardır.

Bunlar;

  1. Authorization code grant
  2. Implicit grant
  3. Resource owner credentials grant
  4. Client credentials grant

Bu izin tiplerine göre AouthServer bize token dönüyor. Burada biz sadece Client credentials grant ‘i dikkate alalım. Yani kimlik ile beraber bir izin alma işlemi. İlk 3 izin türünü eğer kullanıcı adı şifre gibi login işlemi de var ise kullanmamız gerekiyor. Ancak eğer kullanıcı ile ilgili işlem yok ise client credential kullanmamız gerekiyor.

Bu OAuth 2.0 protokolünün kurallarıdır. Detaylı bilgi için yukarıda paylaşmış olduğum adresten inceleyebilirsiniz. Yine IdentityServer4 hakkında detaylı bilgi için de buradan ilgili dokümantasyonu inceleyebilirisiniz

Şimdi kodlamamıza geri dönelim .

Öncelikle AuthServer projesine Manage Nuget üzerinden IdentityServer4 Frameworkünün güncel versiyonunu yükleyelim.

Ardından AuthServer projesine Config.cs adında bir class ekleyelim ve clasın içine aşağıdaki iki metodu yazalım.

Bu iki metot tan ;

GetApiResources() : Hangi API’lere ( API1,API2,API3 gibi ) erişim izni ile ilgilidir.

GetApiScopes(): Hangi API’lere hangi CRUD izni (read,write,update gibi) olacağı ile ilgilidir.

Şimdi GetApiResources ve GetApiScopes’ları AouthServer’a tanıttığımıza göre Clientlarımız da tanıtalım.

Burada GetClients() metodu ile iki adet clientı tanımlıyoruz.

Clientlarımızın “AllowedGrantTypes”’larını “ClientCredentials” olarak tanımlıyoruz çünkü yukarıda da belirttiğim gibi bir login işlemi gerektirmeyen bir erişim sağlıyoruz.

“AllowedScopes” ile de hangi clientin hangi apiye hangi erişim izni olacağını (read,write,update gibi) belirtiyoruz.

Şimdi bu metotları startup clasında konfigüre edelim.

Burada “AddInMemory” kullandık. Çünkü henüz bir database’imiz yok bu yüzden datalarımızı Inmemory’de tutacağız.

Şimdi artık AouthServer projemizi ayağa kaldırıp ilgili client bilgileri ile token isteği atabiliriz.

Postman üzerinden http://locallhost:5001/connect/token URL’ine yukarıdaki gibi ilgili client bilgisi ile Client1 için istek attığımızda bize bir token döndürecektir. Bu token ile api1 API’sine read,update ve write erişim izinleri sağlanmış oldu.

Not: Client-Credentials izin tipinde refresh token kullanılamaz ama diğer izin tiplerinde (Authorization code grant Implicit grant Resource owner credentials grant) refresh token kullanılabilir.

Şuana kadar AuthServer servisimizi tanımladık. İlgili API ve Client ile konuşacak hale getirdik. Şimdi gelin API’lerimizi AuthServer servisi ile konuşacak duruma getirelim.

Öncelikle token ile haberleşeceğimiz için Asp.net Core projemize JsonWebtoken paketini kurmamız gerekiyor.

Ardından JsonWebtoken ı Startup.cs clasımızda inject edelim.

burada opts üzerinden 3 adet property görüyorsunuz. Bunlar;

Authority: tokenı yayınlayan servisin URL’ilini tutar.

Audience: Datayı alacak servisin resource propertisi. Bu bilgiyi biz AuthServer servisindeki Config.cs clasında GetApiResources() metodu içierisinde “ApiResource” olarak tanımlamıştık.

RequireHttpsMetadata: Meta veri adresi veya yetkisi için HTTPS’nin gerekli olup olmadığını alır veya ayarlar. Varsayılan değeri true dir.

Ardından Configure metodu içine UseAuthentication() ve UseAuthentication() metotlarını midilware olarak ekliyoruz.

Biz bu işlemi API1 servisi için yaptık aynı işlem bir de API2 servisi için yapılacak.

Şimdi artık IdentityServer4 ile koruyacağımız API servsimizde bir controller oluşturalım ve bu controllerdan bir data döndürelim.

Bir Product.cs modeli oluşturduk ve controller üzerinden örnek datalar vererek bu product üzerinden CRUD metorlarını yazdık. Artık Action metodu yada controller üzerine [Authorize] yazarak API’mizi IdentityServer ile korumuş olduk.

Şimdi artık servislerimizi ayağa kaldırarak AuthServer servisine client bilgisi ile token isteği atabilir ver ardından dönen token ile ilgili API’lere erişebiliriz.

Şimdi de API’lerimize rol bazlı yetkilendirme verelim. Bunun için Startup.cs clasında ConfigureServices metodunda küçük bir kodlama yapmamız gerekiyor.

Koddan da anlaşılacağı üzerine API’miz için iki adet rol bazlı yetkilendirme türünü belirtik.

Bunlardan biri “ReadProduct”. Bu bu roldeki bir client isteği geldiğinde API mizedeki product için sadece read izni olacaktır. Bir diğeri ise “UpdateOrCreate”. Bu da update ve create izni sağlayacaktır.

Şimdi controller metotlarımıza bu rol bazlı yetkilendirmeye göre erişim sağlayalım.

Artık metotlarımızın başında [Authorize(Policy = “UpdateOrCreate”)]ve [Authorize(Policy = “ReadProduct”)] yazarak metotlarımıza rol bazlı yetkilendirmeyi vermiş olduk.

Buraya kadar AoutheServis servisimizi ve API servislerimizi birbirleri ile IdentitiyServer framework’ü ile konuşacak hale getirdik. Şimdi son olarak client servislerimiz de bu servisler ile konuşacak duruma getirelim.

Öncelikle client bilgilerimizi her seferinde girmemek adında appsetting.json da saklıyoruz.

Şimdi bir servis clası tanımlayalım. Bu clasımıza yazdığımız metot ile controllerdan client bilgilerine erişim sağlayalım.

Ardından oluşturduğumuz bu interface’yi Startup.cs clasında inject edelim.

Ardından Startup ta Authentication konfigürasyonumuzu oluşturalım.

Burada “Authority” property si ile token isteği atacağımız AuthServer URL’ini tanıtmış olduk.

Ardından ProuctController Clasımızı oluşturalım ve ilgili api’lere istekte bulunalım.

controller clasımızda bir client oluşturduk ve bu client üzerinden ilgili URL’e istek atmış bulunduk.

Böylece client’ımız önce AuthServer URL’ine client bilgisi ile istekte bulunarak bir token isteğinde bulundu. Dönen token ile API’ye bir get isteğinde bulundu. API bize bir product listesi döndürmüş oldu.

Benim anlatacaklarım bu kadardı. Umarım bu yazı anlaşılır ve sizlere faydalı olmuştur.

Detaylı incelemeniz için kodalara github linkinden erişebilirsiniz.

Hepinize teşekkür ederim…

Github: https://github.com/KaraZeki/MediumIdentityServer

--

--