diff --git a/src/Fancy.ResourceLinker.Gateway/Authentication/TokenService.cs b/src/Fancy.ResourceLinker.Gateway/Authentication/TokenService.cs index c346771..17c477d 100644 --- a/src/Fancy.ResourceLinker.Gateway/Authentication/TokenService.cs +++ b/src/Fancy.ResourceLinker.Gateway/Authentication/TokenService.cs @@ -64,7 +64,7 @@ internal async Task SaveTokenForNewSessionAsync(OpenIdConnectMessage tok { // Create a new guid for the new session string sessionId = Guid.NewGuid().ToString(); - await SaveOrUpdateTokenAsync (sessionId, tokenResponse); + await SaveOrUpdateTokenAsync(sessionId, tokenResponse); return sessionId; } diff --git a/src/Fancy.ResourceLinker.Gateway/Routing/Auth/Auth0ClientCredentialOnlyAuthStrategy.cs b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/Auth0ClientCredentialOnlyAuthStrategy.cs new file mode 100644 index 0000000..d736d77 --- /dev/null +++ b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/Auth0ClientCredentialOnlyAuthStrategy.cs @@ -0,0 +1,71 @@ +using Fancy.ResourceLinker.Gateway.Authentication; +using Fancy.ResourceLinker.Gateway.Common; +using Microsoft.Extensions.Logging; + +namespace Fancy.ResourceLinker.Gateway.Routing.Auth; + +/// +/// A route authentication strategy running the OAuth client credential flow only. +/// +/// +/// In some situations, auth0 requires an audience parameter in the request. This once can be added with this auth strategy. +/// +internal class Auth0ClientCredentialOnlyAuthStrategy : ClientCredentialOnlyAuthStrategy +{ + /// + /// The name of the auth strategy. + /// + public new const string NAME = "Auth0ClientCredentialOnly"; + + // + /// The auth0 audience. + /// + private string _audience = string.Empty; + + /// + /// Initializes a new instance of the class. + /// + /// The discovery document service. + /// The logger. + public Auth0ClientCredentialOnlyAuthStrategy(DiscoveryDocumentService discoveryDocumentService, ILogger logger) : base(discoveryDocumentService, logger) + { + } + + /// + /// Gets the name of the strategy. + /// + /// + /// The name. + /// + public override string Name => NAME; + + /// + /// Initializes the authentication strategy based on the gateway authentication settings and the route authentication settings asynchronous. + /// + /// The gateway authentication settigns. + /// The route authentication settigns. + public override Task InitializeAsync(GatewayAuthenticationSettings? gatewayAuthenticationSettings, RouteAuthenticationSettings routeAuthenticationSettings) + { + if (routeAuthenticationSettings.Options.ContainsKey("Audience")) + { + _audience = routeAuthenticationSettings.Options["Audience"]; + } + + return base.InitializeAsync(gatewayAuthenticationSettings, routeAuthenticationSettings); + } + + /// + /// Sets up the token request. + /// + /// The token request. + protected override Dictionary SetUpTokenRequest() + { + return new Dictionary + { + { "grant_type", "client_credentials" }, + { "client_id", _clientId }, + { "client_secret", _clientSecret }, + { "scope", _scope } + }; + } +} diff --git a/src/Fancy.ResourceLinker.Gateway/Routing/Auth/ClientCredentialOnlyAuthStrategy.cs b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/ClientCredentialOnlyAuthStrategy.cs index 11f02cb..76f4944 100644 --- a/src/Fancy.ResourceLinker.Gateway/Routing/Auth/ClientCredentialOnlyAuthStrategy.cs +++ b/src/Fancy.ResourceLinker.Gateway/Routing/Auth/ClientCredentialOnlyAuthStrategy.cs @@ -65,32 +65,32 @@ internal class ClientCredentialOnlyAuthStrategy : IRouteAuthenticationStrategy /// /// The discovery document. /// - private DiscoveryDocument? _discoveryDocument; + protected DiscoveryDocument? _discoveryDocument; /// /// The client identifier. /// - private string _clientId = string.Empty; + protected string _clientId = string.Empty; /// /// The client secret. /// - private string _clientSecret = string.Empty; + protected string _clientSecret = string.Empty; /// /// The scope. /// - private string _scope = string.Empty; + protected string _scope = string.Empty; /// /// The is initialized. /// - private bool _isInitialized = false; + protected bool _isInitialized = false; /// /// The current token response. /// - private ClientCredentialsTokenResponse? _currentTokenResponse; + protected ClientCredentialsTokenResponse? _currentTokenResponse; /// /// Initializes a new instance of the class. @@ -109,14 +109,14 @@ public ClientCredentialOnlyAuthStrategy(DiscoveryDocumentService discoveryDocume /// /// The name. /// - public string Name => NAME; + public virtual string Name => NAME; /// /// Initializes the authentication strategy based on the gateway authentication settings and the route authentication settings asynchronous. /// /// The gateway authentication settigns. /// The route authentication settigns. - public async Task InitializeAsync(GatewayAuthenticationSettings? gatewayAuthenticationSettings, RouteAuthenticationSettings routeAuthenticationSettings) + public virtual async Task InitializeAsync(GatewayAuthenticationSettings? gatewayAuthenticationSettings, RouteAuthenticationSettings routeAuthenticationSettings) { string authority; @@ -210,6 +210,21 @@ public async Task SetAuthenticationAsync(IServiceProvider serviceProvider, HttpR request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } + /// + /// Sets up the token request. + /// + /// The token request. + protected virtual Dictionary SetUpTokenRequest() + { + return new Dictionary + { + { "grant_type", "client_credentials" }, + { "client_id", _clientId }, + { "client_secret", _clientSecret }, + { "scope", _scope } + }; + } + /// /// Gets the access token asynchronous. /// @@ -230,13 +245,7 @@ private async Task GetAccessTokenAsync() /// private async Task GetTokenViaClientCredentialsAsync() { - var payload = new Dictionary - { - { "grant_type", "client_credentials" }, - { "client_id", _clientId }, - { "client_secret", _clientSecret }, - { "scope", _scope } - }; + Dictionary payload = SetUpTokenRequest(); HttpClient httpClient = new HttpClient(); @@ -262,7 +271,7 @@ private async Task GetTokenViaClientCredentialsA ClientCredentialsTokenResponse? result = await response.Content.ReadFromJsonAsync(); - if(result == null) + if (result == null) { throw new InvalidOperationException("Could not deserialize client credential token response"); }