Yazılım Mimarileri ve Tasarım Desenleri Üzerine

IdentityServer4 Yazı Serisi #14 – Merkezi Üyelik Sistemi – Refresh Token İle Yeni Access Token Alma

Merhaba,

IdentityServer4 Yazı Serisinin bir önceki Merkezi Üyelik Sistemi – Access Token İle API’lerle Haberleşme başlıklı makalemizde IdentityServer’dan elde edilen access token ile API’lara nasıl istek yapıldığını ele almıştık. Bu içeriğimizde ise client tarafında authentication property’ler arasında elde edilen refresh token’ı kullanarak nasıl yeni bir access token ve id token’ın alınabileceğini ve bunların mevcut authentication propertyler ile nasıl değiştirilebileceğini inceleyeceğiz.

Bizler refresh token örneklendirmesini, bu ondördüncü makaleye kadar hasbel kader geliştirdiğimiz IdentityServer4Example uygulaması üzerinden irdeleyeceğiz. Geliştirdiğimiz uygulamanın son versiyonu zaten mevcudiyette refresh token üretimi için tüm alt yapıyı sağladığından dolayı direkt olarak refresh token ile access token talebini ele alacak ve bu işlemin mantığını daha net kavrayabilmek için, Postman ve client uygulaması olmak üzere iki farklı istemcide ayrı ayrı örneklendireceğiz.

Postman’de Refresh Token İle Yeni Token Alma

İlk olarak client uygulamasında bir refresh token elde edelim.

Ardından bu refresh token değerini kullanarak Postman uygulaması üzerinden aşağıdaki konfigürasyonlar eşliğinde yeni bir access token talebinde bulunalım.

client_id Client id değeri.
client_secret Client secret değeri.
grant_type İstek türü. Hangi istek yapılacaksa ona uygun tür bildirilmelidir. Bizler refresh token talebinde bulunacağımızdan dolayı ‘refresh_token’ değerini vereceğiz. Diğer taleplere nazaran alabileceği değerleri orjinal kaynağından ‘grant_type’ başlığı altında inceleyebilirsiniz.
username Kullanıcı adı.
password Kullanıcı şifresi.
refresh_token Refresh token değeri. Yeni bir access token değeri talep edebilmek için mevcudiyetteki refresh token değerinin verilmesi gerekmektedir.

Yukarıdaki ekran görüntüsünde görüldüğü üzere her talep neticesinde yeni bir access token ve refresh token üretilmektedir. Her talepte access token’ından ziyade refresh token’ın yeniden üretilme sebebi ise Auth Server’da ilgili client’ı tanımlayan nesnede ‘RefreshTokenUsage’ özelliğine ‘OneTimeOnly’ değerinin verilmesidir. Eğer ki ‘ReUse’ değeri verilseydi her talep neticesinde aynı refresh token değeri kullanılabilecekti.

Client Uygulamasında Refresh Token İle Yeni Token Alma

Esas itibarıyla refresh token ile client uygulaması üzerinden access token talebinde bulunulması gerekecektir. Bu duruma istinaden aşağıdaki örneği irdelemekte fayda vardır.

    public class AuthController : Controller
    {
        public async Task<IActionResult> NewAccessToken()
        {
            string refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
            HttpClient httpClient = new HttpClient();
            RefreshTokenRequest refreshTokenRequest = new RefreshTokenRequest()
            {
                ClientId = "OnlineBankamatik",
                ClientSecret = "onlinebankamatik",
                RefreshToken = refreshToken,
                Address = (await httpClient.GetDiscoveryDocumentAsync("https://localhost:1000")).TokenEndpoint
            };
            TokenResponse tokenResponse = await httpClient.RequestRefreshTokenAsync(refreshTokenRequest);
            AuthenticationProperties properties = (await HttpContext.AuthenticateAsync()).Properties;

            properties.StoreTokens(
                new List<AuthenticationToken> {
                  new AuthenticationToken
                                         {
                                             Name = OpenIdConnectParameterNames.IdToken,
                                             Value = tokenResponse.IdentityToken
                                         },
                  new AuthenticationToken
                                         {
                                             Name = OpenIdConnectParameterNames.AccessToken,
                                             Value = tokenResponse.AccessToken
                                         },
                  new AuthenticationToken
                                         {
                                             Name = OpenIdConnectParameterNames.RefreshToken,
                                             Value = tokenResponse.RefreshToken
                                         },
                  new AuthenticationToken
                                         {
                                             Name = OpenIdConnectParameterNames.ExpiresIn,
                                             Value = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString("O")
                                         },
                                       });
            await HttpContext.SignInAsync("OnlineBankamatikCookie", (await HttpContext.AuthenticateAsync()).Principal, properties);
            return RedirectToAction(nameof(BankamatikController.Index));
        }
        public async Task<IActionResult> Index()
        {
            AuthenticateResult authenticateResult = await HttpContext.AuthenticateAsync();
            IOrderedEnumerable<KeyValuePair<string, string>> properties = authenticateResult.Properties.Items.OrderBy(p => p.Key);
            return View(properties);
        }
    }

Yukarıdaki kod bloğunun 5 ile 14. satırları arasında refresh token ile yeni bir access token talebinde bulunulması, 15 ile 41. satırları arasında ise elde edilen authentication property’ler ile mevcudiyette bulunanların değiştirilmesi ele alınmıştır. Tek tek bu kodları izah etmemiz gerekirse eğer;


Görüldüğü üzere refresh token ile yeni bir access token talep edilmekte ve elde edilen tüm değerler öncekileriyle değiştirilmektedir.

İ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.

Mobil sürümden çık