From fca788914c287b35f15fd3d5ae82599b6f8a37ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 28 Nov 2022 10:25:20 +0100 Subject: [PATCH] Abort authentication demands with an explicit grant type if it's not listed as supported in the server configuration --- .../OpenIddictResources.resx | 3 + .../OpenIddictClientSystemNetHttpHandlers.cs | 3 +- ...tClientWebIntegrationHandlers.Discovery.cs | 56 +++++++++++++++++-- ...penIddictClientWebIntegrationProviders.xml | 6 +- .../OpenIddictClientHandlers.cs | 7 +++ ...enIddictValidationSystemNetHttpHandlers.cs | 3 +- 6 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/OpenIddict.Abstractions/OpenIddictResources.resx b/src/OpenIddict.Abstractions/OpenIddictResources.resx index 23dd0ff7..28aeb044 100644 --- a/src/OpenIddict.Abstractions/OpenIddictResources.resx +++ b/src/OpenIddict.Abstractions/OpenIddictResources.resx @@ -1381,6 +1381,9 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A No response mode enabled in the client options could be found in the list of response modes allowed by the client registration, which typically indicates an invalid configuration. Ensure the 'OpenIddictClientRegistration.ResponseModes' collection contain at least one of the response modes enabled in the client options or leave it empty to allow OpenIddict to negotiate all the enabled response modes. + + The specified grant type ({0}) is not listed as a supported grant type in the server configuration. If the error persists, ensure the supported grant types listed in the authorization server configuration are appropriate. + The security token is missing. diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs index 834133fb..6b944202 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs @@ -7,7 +7,6 @@ using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO.Compression; using System.Net.Http.Headers; using Microsoft.Extensions.Logging; @@ -125,7 +124,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue(Charsets.Utf8)); // Note: for security reasons, HTTP compression is never opted-in by default. Providers - // that require using HTTP compression that register a custom event handler to send an + // that require using HTTP compression can register a custom event handler to send an // Accept-Encoding header containing the supported algorithms (e.g GZip/Deflate/Brotli). return default; diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs index b9e375c8..1a3afd7c 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs @@ -19,7 +19,8 @@ public static partial class OpenIddictClientWebIntegrationHandlers * Configuration response handling: */ AmendIssuer.Descriptor, - AmendClientAuthenticationMethods.Descriptor, + AmendGrantTypes.Descriptor, + AmendTokenEndpointClientAuthenticationMethods.Descriptor, AmendCodeChallengeMethods.Descriptor, AmendEndpoints.Descriptor); @@ -64,17 +65,62 @@ public static partial class OpenIddictClientWebIntegrationHandlers } /// - /// Contains the logic responsible for amending the supported - /// client authentication methods for the providers that require it. + /// Contains the logic responsible for amending the supported grant types for the providers that require it. + /// + public sealed class AmendGrantTypes : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(ExtractGrantTypes.Descriptor.Order + 500) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(HandleConfigurationResponseContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + // Note: some providers don't list the grant types they support, which prevents the OpenIddict + // client from using them (unless they are assumed to be enabled by default, like the + // authorization code or implicit flows). To work around that, the list of supported grant + // types is amended to include the known supported types for the providers that require it. + + if (context.Registration.ProviderName is Providers.Apple) + { + context.Configuration.GrantTypesSupported.Add(GrantTypes.AuthorizationCode); + context.Configuration.GrantTypesSupported.Add(GrantTypes.RefreshToken); + } + + else if (context.Registration.ProviderName is Providers.Cognito or Providers.Microsoft) + { + context.Configuration.GrantTypesSupported.Add(GrantTypes.AuthorizationCode); + context.Configuration.GrantTypesSupported.Add(GrantTypes.ClientCredentials); + context.Configuration.GrantTypesSupported.Add(GrantTypes.RefreshToken); + } + + return default; + } + } + + /// + /// Contains the logic responsible for amending the client authentication + /// methods supported by the token endpoint for the providers that require it. /// - public sealed class AmendClientAuthenticationMethods : IOpenIddictClientHandler + public sealed class AmendTokenEndpointClientAuthenticationMethods : IOpenIddictClientHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() - .UseSingletonHandler() + .UseSingletonHandler() .SetOrder(ExtractTokenEndpointClientAuthenticationMethods.Descriptor.Order + 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index 8e6630ba..7b9ca0af 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -15,10 +15,12 @@ + + Description="The AWS region" /> + + Description="The User Pool ID" /> diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs index b3c7478b..cd8f3715 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs @@ -284,6 +284,13 @@ public static partial class OpenIddictClientHandlers { throw new InvalidOperationException(SR.GetResourceString(SR.ID0307)); } + + // Ensure the selected grant type, if explicitly set, is listed as supported in the configuration. + if (!string.IsNullOrEmpty(context.GrantType) && + !context.Configuration.GrantTypesSupported.Contains(context.GrantType)) + { + throw new InvalidOperationException(SR.FormatID0363(context.GrantType)); + } } } diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs index 8063fca9..9db99571 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs @@ -7,7 +7,6 @@ using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO.Compression; using System.Net.Http.Headers; using Microsoft.Extensions.Logging; @@ -124,7 +123,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue(Charsets.Utf8)); // Note: for security reasons, HTTP compression is never opted-in by default. Providers - // that require using HTTP compression that register a custom event handler to send an + // that require using HTTP compression can register a custom event handler to send an // Accept-Encoding header containing the supported algorithms (e.g GZip/Deflate/Brotli). return default;