From c8f7c2c5bb2fd2e09c4c20c5cdc01005ae7e124e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Sat, 16 Dec 2023 01:04:41 +0100 Subject: [PATCH] Declare OpenIddictClientRegistration.ConfigurationManager as a nullable property --- .../OpenIddictResources.resx | 3 + .../OpenIddictClientHandlers.Protection.cs | 3 +- .../OpenIddictClientHandlers.cs | 163 +++++++++++------- .../OpenIddictClientRegistration.cs | 2 +- .../OpenIddictClientService.cs | 15 ++ 5 files changed, 119 insertions(+), 67 deletions(-) diff --git a/src/OpenIddict.Abstractions/OpenIddictResources.resx b/src/OpenIddict.Abstractions/OpenIddictResources.resx index e8d130a8..c467b571 100644 --- a/src/OpenIddict.Abstractions/OpenIddictResources.resx +++ b/src/OpenIddict.Abstractions/OpenIddictResources.resx @@ -1572,6 +1572,9 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId At least one subject type must be supported. + + A configuration manager must be attached to the client registration to be able to resolve the server configuration. + The security token is missing. diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs index 90acc576..17b39ad3 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs @@ -305,7 +305,8 @@ public static partial class OpenIddictClientHandlers // If validation failed because of an unrecognized key identifier and a client // registration is available, inform the configuration manager that the configuration // MAY have be refreshed by sending a new discovery request to the authorization server. - if (context.Registration is not null && result.Exception is SecurityTokenSignatureKeyNotFoundException) + if (result.Exception is SecurityTokenSignatureKeyNotFoundException && + context.Registration.ConfigurationManager is not null) { context.Registration.ConfigurationManager.RequestRefresh(); } diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs index d065c756..faef0475 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs @@ -423,26 +423,34 @@ public static partial class OpenIddictClientHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0408)); } - try + // Resolve and attach the server configuration to the context if none has been set already. + if (context.Configuration is null) { - // Resolve and attach the server configuration to the context if none has been set already. - context.Configuration ??= await context.Registration.ConfigurationManager - .GetConfigurationAsync(context.CancellationToken) - .WaitAsync(context.CancellationToken) ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); - } + if (context.Registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && - exception is not OperationCanceledException) - { - context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); + try + { + context.Configuration = await context.Registration.ConfigurationManager + .GetConfigurationAsync(context.CancellationToken) + .WaitAsync(context.CancellationToken) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + } - context.Reject( - error: Errors.ServerError, - description: SR.GetResourceString(SR.ID2170), - uri: SR.FormatID8000(SR.ID2170)); + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && + exception is not OperationCanceledException) + { + context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); - return; + context.Reject( + error: Errors.ServerError, + description: SR.GetResourceString(SR.ID2170), + uri: SR.FormatID8000(SR.ID2170)); + + return; + } } // Ensure the selected grant type, if explicitly set, is listed as supported in the configuration. @@ -1019,28 +1027,37 @@ public static partial class OpenIddictClientHandlers // Note: if the static registration cannot be found in the options, this may indicate // the client was removed after the authorization dance started and thus, can no longer // be used to authenticate users. In this case, throw an exception to abort the flow. - context.Registration = await _service.GetClientRegistrationByIdAsync(context.RegistrationId, context.CancellationToken); + context.Registration ??= await _service.GetClientRegistrationByIdAsync(context.RegistrationId, context.CancellationToken); - try + // Resolve and attach the server configuration to the context if none has been set already. + if (context.Configuration is null) { - // Resolve and attach the server configuration to the context. - context.Configuration = await context.Registration.ConfigurationManager - .GetConfigurationAsync(context.CancellationToken) - .WaitAsync(context.CancellationToken) ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); - } + if (context.Registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && - exception is not OperationCanceledException) - { - context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); + try + { + // Resolve and attach the server configuration to the context. + context.Configuration = await context.Registration.ConfigurationManager + .GetConfigurationAsync(context.CancellationToken) + .WaitAsync(context.CancellationToken) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + } - context.Reject( - error: Errors.ServerError, - description: SR.GetResourceString(SR.ID2170), - uri: SR.FormatID8000(SR.ID2170)); + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && + exception is not OperationCanceledException) + { + context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); - return; + context.Reject( + error: Errors.ServerError, + description: SR.GetResourceString(SR.ID2170), + uri: SR.FormatID8000(SR.ID2170)); + + return; + } } } } @@ -4209,26 +4226,34 @@ public static partial class OpenIddictClientHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0408)); } - try + // Resolve and attach the server configuration to the context if none has been set already. + if (context.Configuration is null) { - // Resolve and attach the server configuration to the context if none has been set already. - context.Configuration ??= await context.Registration.ConfigurationManager - .GetConfigurationAsync(context.CancellationToken) - .WaitAsync(context.CancellationToken) ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); - } + if (context.Registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && - exception is not OperationCanceledException) - { - context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); + try + { + context.Configuration = await context.Registration.ConfigurationManager + .GetConfigurationAsync(context.CancellationToken) + .WaitAsync(context.CancellationToken) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + } - context.Reject( - error: Errors.ServerError, - description: SR.GetResourceString(SR.ID2170), - uri: SR.FormatID8000(SR.ID2170)); + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && + exception is not OperationCanceledException) + { + context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); - return; + context.Reject( + error: Errors.ServerError, + description: SR.GetResourceString(SR.ID2170), + uri: SR.FormatID8000(SR.ID2170)); + + return; + } } } } @@ -5852,26 +5877,34 @@ public static partial class OpenIddictClientHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0408)); } - try + // Resolve and attach the server configuration to the context if none has been set already. + if (context.Configuration is null) { - // Resolve and attach the server configuration to the context if none has been set already. - context.Configuration ??= await context.Registration.ConfigurationManager - .GetConfigurationAsync(context.CancellationToken) - .WaitAsync(context.CancellationToken) ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); - } + if (context.Registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && - exception is not OperationCanceledException) - { - context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); + try + { + context.Configuration = await context.Registration.ConfigurationManager + .GetConfigurationAsync(context.CancellationToken) + .WaitAsync(context.CancellationToken) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + } - context.Reject( - error: Errors.ServerError, - description: SR.GetResourceString(SR.ID2170), - uri: SR.FormatID8000(SR.ID2170)); + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception) && + exception is not OperationCanceledException) + { + context.Logger.LogError(exception, SR.GetResourceString(SR.ID6219)); - return; + context.Reject( + error: Errors.ServerError, + description: SR.GetResourceString(SR.ID2170), + uri: SR.FormatID8000(SR.ID2170)); + + return; + } } } } diff --git a/src/OpenIddict.Client/OpenIddictClientRegistration.cs b/src/OpenIddict.Client/OpenIddictClientRegistration.cs index 980413bb..1fbe91cb 100644 --- a/src/OpenIddict.Client/OpenIddictClientRegistration.cs +++ b/src/OpenIddict.Client/OpenIddictClientRegistration.cs @@ -143,7 +143,7 @@ public sealed class OpenIddictClientRegistration /// /// Gets or sets the configuration manager used to retrieve and cache the server configuration. /// - public IConfigurationManager ConfigurationManager { get; set; } = default!; + public IConfigurationManager? ConfigurationManager { get; set; } /// /// Gets or sets the URI of the configuration endpoint exposed by the server. diff --git a/src/OpenIddict.Client/OpenIddictClientService.cs b/src/OpenIddict.Client/OpenIddictClientService.cs index 494cfe20..04955632 100644 --- a/src/OpenIddict.Client/OpenIddictClientService.cs +++ b/src/OpenIddict.Client/OpenIddictClientService.cs @@ -154,6 +154,11 @@ public sealed class OpenIddictClientService } var registration = await GetClientRegistrationAsync(issuer, cancellationToken); + if (registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } + return await registration.ConfigurationManager .GetConfigurationAsync(cancellationToken) .WaitAsync(cancellationToken) ?? @@ -182,6 +187,11 @@ public sealed class OpenIddictClientService } var registration = await GetClientRegistrationAsync(provider, cancellationToken); + if (registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } + return await registration.ConfigurationManager .GetConfigurationAsync(cancellationToken) .WaitAsync(cancellationToken) ?? @@ -207,6 +217,11 @@ public sealed class OpenIddictClientService } var registration = await GetClientRegistrationByIdAsync(identifier, cancellationToken); + if (registration.ConfigurationManager is null) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0422)); + } + return await registration.ConfigurationManager .GetConfigurationAsync(cancellationToken) .WaitAsync(cancellationToken) ??