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;
IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma

  • 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
IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma
İ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;
IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma
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.
    IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma

  • 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.
    IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma

Access Token ile Id Token Arasındaki Fark

Her iki JWT değerini jwt.io sitesi üzerinden incelersek eğer;

Access Token Id Token
IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma
Her iki değerin açılımına göz atarsanız eğer kendilerine has belli başlı bilgilerin yanında, access token, erişimi sağlayabilmesi için ‘scope’ altında yetkiler barındırmaktadır. Lakin id token’da ‘scope’ yer almamaktadır. Burada id token’ın yukarılarda bahsedildiği gibi sadece doğrulama amaçlı üretilen bir değer olduğu daha da netleşmiş olmaktadır.

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.
IdentityServer4 Yazı Serisi #12 - Merkezi Üyelik Sistemi - Claim ve Authentication Propertyleri Okuma
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.

Bunlar da hoşunuza gidebilir...

3 Cevaplar

  1. 07 Kasım 2020

    […] önceki Merkezi Üyelik Sistemi – Claim ve Authentication Propertyleri Okuma başlıklı makalemizde IdentityServer4 mimarisinden claim bilgileri ile birlikte access token, […]

  2. 24 Kasım 2020

    […] metotlardan ilki için UserInfo Endpoint‘inin programatik kısmını temsil ediyor diyebiliriz. Dinamik olarak claim oluşturma ve […]

  3. 25 Kasım 2020

    […] metotlardan ilki için UserInfo Endpoint‘inin programatik kısmını temsil ediyor diyebiliriz. Dinamik olarak claim oluşturma ve […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*