From 41e2827fe63190dfeb59feafccf49d0dd59625b7 Mon Sep 17 00:00:00 2001 From: miseeger Date: Fri, 15 Nov 2024 22:13:52 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20for=20AzureOnBehalfOfAuthStrategy=20The?= =?UTF-8?q?=20on-behalf=20token=20was=20not=20cached=20per=20request=20in?= =?UTF-8?q?=20the=20strategy=20method,=20but=20was=20always=20set=20once?= =?UTF-8?q?=20with=20the=20token=20of=20the=20first=20requesting=20user=20?= =?UTF-8?q?when=20the=20strategy=20method=20was=20called=20for=20the=20ver?= =?UTF-8?q?y=20first=20time.=20This=20token=20was=20then=20the=20token=20f?= =?UTF-8?q?or=20ANY=20user=20that=20was=20routed=20to=20the=20APIs=20(?= =?UTF-8?q?=E2=80=9Con=20behalf=20of=E2=80=9D)=20via=20the=20gateway=20unt?= =?UTF-8?q?il=20the=20next=20restart=20of=20the=20gateway.=20Each=20on-beh?= =?UTF-8?q?alf=20token=20is=20now=20cached=20with=20the=20unique,=20incomi?= =?UTF-8?q?ng=20session=20ID=20of=20the=20requesting=20user=20and=20can=20?= =?UTF-8?q?therefore=20be=20retrieved=20correctly=20when=20needed=20again.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Auth/AzureOnBehalfOfAuthStrategy.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Fancy.ResourceLinker.Gateway/Routing/Auth/AzureOnBehalfOfAuthStrategy.cs b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/AzureOnBehalfOfAuthStrategy.cs index 0fe99bf..22b5e90 100644 --- a/src/Fancy.ResourceLinker.Gateway/Routing/Auth/AzureOnBehalfOfAuthStrategy.cs +++ b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/AzureOnBehalfOfAuthStrategy.cs @@ -1,4 +1,5 @@ -using Fancy.ResourceLinker.Gateway.Authentication; +using System.Collections.Concurrent; +using Fancy.ResourceLinker.Gateway.Authentication; using Fancy.ResourceLinker.Gateway.Common; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; @@ -93,9 +94,10 @@ internal class AzureOnBehalfOfAuthStrategy : IRouteAuthenticationStrategy private DiscoveryDocument? _discoveryDocument; /// - /// The current token response. + /// The currently in-use token responses per SessionId. /// - private OnBehalfOfTokenResponse? _currentTokenResponse; + // private ConcurrentDictionary _cachedTokenResponses; + private ConcurrentDictionary _cachedTokenResponses = new (); /// /// Initializes a new instance of the class. @@ -165,26 +167,31 @@ public async Task SetAuthenticationAsync(IServiceProvider serviceProvider, HttpR string accessToken = await GetAccessTokenAsync(serviceProvider); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } - + /// /// Gets the access token asynchronous. /// /// The access token. private async Task GetAccessTokenAsync(IServiceProvider serviceProvider) { - if (_currentTokenResponse == null || IsExpired(_currentTokenResponse)) + var tokenService = TryGetTokenService(serviceProvider); + + if (tokenService == null) { - TokenService? tokenService = TryGetTokenService(serviceProvider); + throw new InvalidOperationException("A token service in a scope is needed to use the azure on behalf of flow"); + } - if (tokenService == null) - { - throw new InvalidOperationException("A token service in a scope is needed to use the azure on behalf of flow"); - } + var tokenResponse = _cachedTokenResponses.ContainsKey(tokenService.CurrentSessionId!) + ? _cachedTokenResponses[tokenService.CurrentSessionId!] + : null; - _currentTokenResponse = await GetOnBehalfOfTokenAsync(tokenService); + if (tokenResponse == null || IsExpired(tokenResponse)) + { + tokenResponse = await GetOnBehalfOfTokenAsync(tokenService); + _cachedTokenResponses.TryAdd(tokenService.CurrentSessionId!, tokenResponse); } - return _currentTokenResponse.AccessToken; + return tokenResponse.AccessToken; } ///