diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index ce95ec24..f4c8b463 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -28,6 +28,8 @@ public static partial class OpenIddictClientWebIntegrationHandlers AdjustRedirectUriInTokenRequest.Descriptor, OverrideValidatedBackchannelTokens.Descriptor, DisableBackchannelIdentityTokenNonceValidation.Descriptor, + OverrideUserinfoEndpoint.Descriptor, + DisableUserinfoValidation.Descriptor, AttachAdditionalUserinfoRequestParameters.Descriptor, PopulateUserinfoTokenPrincipalFromTokenResponse.Descriptor, @@ -398,6 +400,87 @@ public static partial class OpenIddictClientWebIntegrationHandlers } } + /// + /// Contains the logic responsible for overriding the address + /// of the userinfo endpoint for the providers that require it. + /// + public sealed class OverrideUserinfoEndpoint : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(ResolveUserinfoEndpoint.Descriptor.Order + 500) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(ProcessAuthenticationContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + context.UserinfoEndpoint = context.Registration.ProviderName switch + { + // SuperOffice doesn't expose a static OpenID Connect userinfo endpoint but offers an API whose + // absolute URI needs to be computed based on a special claim returned in the identity token. + Providers.SuperOffice when + (context.BackchannelIdentityTokenPrincipal ?? // Always prefer the backchannel identity token when available. + context.FrontchannelIdentityTokenPrincipal) is ClaimsPrincipal principal && + Uri.TryCreate(principal.GetClaim("http://schemes.superoffice.net/identity/webapi_url"), UriKind.Absolute, out Uri? uri) + => OpenIddictHelpers.CreateAbsoluteUri(uri, new Uri("v1/user/currentPrincipal", UriKind.Relative)), + + _ => context.UserinfoEndpoint + }; + + return default; + } + } + + /// + /// Contains the logic responsible for disabling the userinfo validation for the providers that require it. + /// + public sealed class DisableUserinfoValidation : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(EvaluateUserinfoRequest.Descriptor.Order + 500) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(ProcessAuthenticationContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + // Note: despite implementing OpenID Connect, some providers are known to implement completely custom + // userinfo endpoints or semi-standard endpoints that don't fully conform to the core specification. + // + // To ensure OpenIddict can be used with these providers, validation is disabled when necessary. + + context.DisableUserinfoValidation = context.Registration.ProviderName switch + { + // SuperOffice doesn't offer a standard OpenID Connect userinfo endpoint. + Providers.SuperOffice => true, + + _ => context.DisableUserinfoValidation + }; + + return default; + } + } + /// /// Contains the logic responsible for attaching additional parameters /// to the userinfo request for the providers that require it. diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index acb9c397..1eb69bb5 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -625,6 +625,20 @@ + + + + + + + +