IdentityServer4 Yazı Serisi #12 – Merkezi Üyelik Sistemi – Claim ve Authentication Propertyleri Okuma
Merhaba,
IdentityServer4 Yazı Serisinin bir önceki kaleme aldığımız Merkezi Üyelik Sistemi Temelleri başlıklı makalemizde client’ın Auth Server’dan authorization code almasını başarmış ve client üzerinde authorize olan kısımlara yetkili bir şekilde erişimi test etmiştik. Bu içeriğimizde ise Auth Server’dan elde edilen authorization code üzerinde bulunan ve client’a gönderilen claim’lerin ve ‘Authentication Propertyleri’nin nasıl okunduğunu/elde edildiğini inceleyeceğiz.
Öncelikle Claim ve Authentication Property terimlerinin ne olduğunu açıklayarak başlayalım;
- Claim Nedir?
Önceden klavyeye almış olduğumuz Claim Bazlı Kimlik Doğrulama başlıklı yazımızda yahut bu serinin dördüncü makalesi olan IdentityServer4 Cleam Bazlı Yetkilendirme başlıklı içeriğimizde claim hakkında yeterlice hasbihalde bulunmuştuk. Dolayısıyla şuana kadar claim’in ne olduğunu çok iyi bilmeniz yüksek ihtimal olduğundan dolayı ne olur ne olmaz diyerek küçük bir açıklama yapıp çok fazla tanıma girmeden geçmekte fayda görüyorum..Claim; kullanıcı hakkında key – value tarzında tutulan ekstra bilgilerdir.
- Authentication Property Nedir?
Authorization code içerisinde taşınan ve access token, id token, refresh token vs. gibi bilgileri tutan propertylerdir.
Claim’lere Erişim?
Authorization code içerisindeki claim’lere erişebilmek için controller sınıflarda User.Claims
komutunun kullanılması yeterlidir. Gelen claim’lere göz atarsak eğer;
- sid
OpenIdConnect tarafından kullanıcıya özel üretilen kullanıcı Id(subid)’yi ifade eder. - http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
Kullanının Subject Id’sine(hatırlarsanız eğer test user tanımlarken bildirmiştik) manuel erişmek gerektiğinde bu sabit üzerinden elde edilebilir. Otomatik şemadır. - auth_time
Saniye cinsinden yetki süresini ifade eder. - http://schemas.microsoft.com/identity/claims/identityprovider
Hangi sağlayıcı üzerinden giriş yapıldıysa onun bilgisini döner. Misal; Facebook ya da Google üzerinden yetki alınsaydı ilgili harici kaynağın adı geçiyor olacaktı. - http://schemas.microsoft.com/claims/authnmethodsreferences
Yetkilendirme sürecinde hangi akış mekanizmasının kullanıldığını ifade eder. ‘pwd’, Resource Owner Credentials Grant(Flow)‘a karşılık gelmektedir.
Evet… Gelen claim’ler işte bu kadar. Şimdi muhtemelen bir önceki makalemizde oluşturulan test user’lar da tanımladığımız ve ‘IdentityResource’ içerisinde new IdentityResources.Profile()
komutu ile authorization code’a eklenmesini söylediğimiz claim’lerin neden gelmediğini soruyor olabilirsiniz.
Test User | IdentityResource |
---|---|
![]() |
![]() |
İlgili claim’lerin eklendiği noktalardaki görseller… |
Bu claim’lerin User.Claims
‘e eklenmemesinin sebebi ilgili cookie yahut token değerinin şişirilmemesidir. İşlevsel olarak IdentityServer4 kütüphanesi UserInfo Endpoint’i üzerinden kullanıcıya dair tüm claim’lerin erişilebilir olmasını sağlamaktadır. Dolayısıyla ihtiyaç yahut istek neticesinde ilgili değerlerin elde edilebilmesi için bahsedilen endpoint’in kullanılması inisiyatife bağlı olacağından dolayı framework geliştiricileri, default olarak harici claim’lerin cookie yahut token’a eklenmesini performans açısından uygun görmemiştir.
Tabi ki de bu durum, istenildiği taktirde kullanıcıya dair tüm claim’lerin üretilecek cookie ya da token değerine eklenmesini engelleyen bir durum demek değildir. Eğer ki tüm claim’lerin otomatik olarak cookie ya da token değerine eklenmesini istiyorsanız ilgili client’ın ‘Startup.cs’ dosyasında aşağıdaki gibi ‘GetClaimsFromUserInfoEndpoint’ konfigürasyonunun yapılması yeterli olacaktır.
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(_ => { _.DefaultScheme = "OnlineBankamatikCookie"; _.DefaultChallengeScheme = "oidc"; }) .AddCookie("OnlineBankamatikCookie") .AddOpenIdConnect("oidc", _ => { _.SignInScheme = "OnlineBankamatikCookie"; _.Authority = "https://localhost:1000"; _.ClientId = "OnlineBankamatik"; _.ClientSecret = "onlinebankamatik"; _.ResponseType = "code id_token"; _.GetClaimsFromUserInfoEndpoint = true; }); services.AddControllersWithViews(); } }
‘GetClaimsFromUserInfoEndpoint’ propertysine ‘true’ değerini set ederek, oluşturulacak cookie yahut token değerlerine sistemde tanımlanmış olan tüm claim’leri eklemiş bulunmaktayız. Burada mimari, arkaplanda Userinfo Endpoint’ine tüm claim’ler için istek göndererek çalışmayı sergileyecektir.
GetClaimsFromUserInfoEndpoint; claim’lerden, profil için default olarak tanımlanmış olan değerleri getirecektir.
name
,family_name
,given_name
,middle_name
,nickname
,preferred_username
,profile
,picture
,website
,gender
,birthdate
,zoneinfo
,locale
,updated_at
Bu ayar lüzumlu lüzumsuz her cookie yahut token üretiminde kullanıcıya dair tüm claim’leri ekleyecektir. Halbuki bizler bu claim’lere erişimi daha iradeli bir şekilde gerçekleştirmek ve ihtiyaca istinaden elde etmek istiyorsak Userinfo Endpoint’ini kullanmamız gerekmektedir.
Authentication Propertylere Erişim?
Authentication propertyler; ‘Access Token’, ‘ID Token’ ve ‘Refresh Token’ olmak üzere temelde üç tanedirler. Auth Server’dan gelen authentication property’lere controller sınıflarından erişebilmek için (await HttpContext.AuthenticateAsync()).Properties.Items
kod konseptinin kullanılması yeterli olacaktır.
İstek neticesinde gelen authentication property’lere göz atarsak eğer;
görüldüğü üzere belli başlı değerler gelmiş bulunmakta lakin hiçbiri operasyonel açıdan bizim için bir anlam ifade etmemektedir. Hani hoca! Access token, refresh token ve id token nerede? diye sorduğunuzu duyar gibiyim 🙂 Evet, böylece authentication property’ler içerisinde ilgili değerlerin default olarak gelmediğini ve özellikle adı geçen parametrelere erişebilmek için ekstradan bildirilerde bulunmamız gerektiğini anlamış bulunmaktayız.
Şimdi sırasıyla bu propertylere nasıl erişilebildiğini inceleyelim;
- Access Token
Client’ın API’lere erişiminde temel yetkiyi sağlayacak olan access token değerinin elde edilebilmesi için ilgili client’ın ‘Startup.cs’ dosyasında ‘SaveTokens’ property’sine ‘true’ değeri set edilmelidir. Böylece Auth server’dan ilgili access token değeri client tarafından elde edilmiş olacaktır.services.AddAuthentication(_ => { _.DefaultScheme = "OnlineBankamatikCookie"; _.DefaultChallengeScheme = "oidc"; }) .AddCookie("OnlineBankamatikCookie") .AddOpenIdConnect("oidc", _ => { . . . _.SaveTokens = true; });
‘SaveTokens’ özelliği varsayılan olarak ‘false’ değerine sahiptir. ‘true’ değeri set edildikten sonra işlevsel olarak, başarılı bir authorization işleminin ardından Authentication Propertylere access token değerini kaydedecektir. Dolayısıyla bizler bu değeri kullanarak hedef API’lardan veri transferini sağlayabileceğiz.
Identity Server tarafından üretilen bir access token’ın default ömrü 1 saattir.
Eğer ki, üretilecek access token’ın ömrünü siz belirlemek istiyorsanız Auth Server’da ki ‘Config.cs’ dosyasında tanımlanan claim’lerden ilgilisinde ‘AccessTokenLifetime’ özelliğini kullanmanız ve saniye cinsinden değer atamanız yeterli olacaktır.
new Client { . . . AccessTokenLifetime = 2 * 60 * 60 }
Velhasıl, bu konfigürasyondan sonra uygulamaları test amaçlı derleyip, çalıştırdığımızda Auth Server’dan gelen cookie içerisinde access token ve id token değerlerini aşağıdaki gibi görebilmekteyiz.
- ID Token
Esas amacı, access token’ın Auth Server tarafından üretilmiş bir token olup olmadığını doğrulamaktır. Identity Server tarafından private key ile imzalanan id token client tarafından elde edilen public key ile doğrulanmakta ve böylece Auth Server tarafından ilgili access token doğrulanmış olmaktadır.Id Token’a erişim sağlanabilmesi için access token’ın erişim konfigürasyonları yeterlidir. Bir önceki adımda sonuç olarak access token yanında id token’da elde edilmiştir.
- Refresh Token
Authentication property’ler arasında bir client için refresh token değerininde elde edilebilmesi için yine Auth Server’da ki ‘Config.cs’ dosyasında ilgili client’a dair ‘AllowOfflineAccess’ özelliğine ‘true’ değerinin verilmesiyle birlikte aşağıdaki konfigürasyonların eklenmesi gerekmektedir.new Client { . . . AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OfflineAccess }, AllowOfflineAccess = true, RefreshTokenUsage = TokenUsage.OneTimeOnly, RefreshTokenExpiration = TokenExpiration.Absolute, AbsoluteRefreshTokenLifetime = 2 * 60 * 60 + (10 * 60) }
Burada ‘RefreshTokenUsage’ propertysi client’a dair üretilecek refresh token’ın kullanılabilirliğini ayarlamaktadır. ‘OneTimeOnly’ değeri yalnızca tek seferlik bir kullanım hakkı tanındığını ifade etmekle birlikte, ‘ReUse’ değeri ile birden fazla kez kullanılabilirlikte ayarlanabilmektedir. ‘AbsoluteRefreshTokenLifetime’ property’si ise refresh token’ın ömrünü belirlemektedir. Burada refresh token ömrü için ‘SlidingRefreshTokenLifetime’da kullanılabilir. İkisi arasındaki fark; ilki net ömrü belirtirken, ikincisi ise belli bir süre içerisinde kullanıldığı taktirde ömrün periyodik uzatılmasını sağlamaktadır.
Bu ayarların dışında ‘AllowedScopes’ property’sine dikkat edilirse eğer
IdentityServerConstants.StandardScopes.OfflineAccess
komutu ile ilgili client’a, üretilecek olan refresh token’a dair erişim yetkisi de verilmektedir.Son olarak ilgili client’ın ‘Startup.cs’ dosyasında yukarıda eklenen OfflineAccess’e karşılık gelen ‘offline_access’ scope değerinin aşağıdaki gibi eklenmesi gerekmektedir.
services.AddAuthentication(_ => { _.DefaultScheme = "OnlineBankamatikCookie"; _.DefaultChallengeScheme = "oidc"; }) .AddCookie("OnlineBankamatikCookie") .AddOpenIdConnect("oidc", _ => { . . . _.Scope.Add("offline_access"); });
Tüm bu işlemler neticesinde uygulama derlenip, çalıştırıldığında refresh token’ın elde edildiği görülecektir.
Access Token ile Id Token Arasındaki Fark
Her iki JWT değerini jwt.io sitesi üzerinden incelersek eğer;
Userinfo Endpoint
Kullanıcı hakkında claim bilgilerini elde etmek için kullanılan endpoint’tir.
/connect/userinfo
endpoint’ine header bilgisi Authorization: Bearer
olan bir ‘GET’ isteğinde bulunulması yeterlidir.
Görüldüğü üzere Userinfo Endpoint ile elde edilen claim’ler, sadece profil için default olarak tanımlanmış değerler değil, tam aksine kullanıcıya dair olan tüm değerlerdir.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
Not : Örnek uygulamayı indirebilmek için buraya tıklayınız.
3 Cevaplar
[…] önceki Merkezi Üyelik Sistemi – Claim ve Authentication Propertyleri Okuma başlıklı makalemizde IdentityServer4 mimarisinden claim bilgileri ile birlikte access token, […]
[…] metotlardan ilki için UserInfo Endpoint‘inin programatik kısmını temsil ediyor diyebiliriz. Dinamik olarak claim oluşturma ve […]
[…] metotlardan ilki için UserInfo Endpoint‘inin programatik kısmını temsil ediyor diyebiliriz. Dinamik olarak claim oluşturma ve […]