From 2e301ce8f29767a1765932ef9d0af755ccaf7e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 15 May 2023 15:52:35 +0200 Subject: [PATCH] Disable userinfo retrieval when a Xbox scope is specified --- .../OpenIddictClientWebIntegrationHandlers.cs | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index 544facdd..ffe5bb28 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -29,6 +29,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers OverrideValidatedBackchannelTokens.Descriptor, DisableBackchannelIdentityTokenNonceValidation.Descriptor, OverrideUserinfoEndpoint.Descriptor, + DisableUserinfoRetrieval.Descriptor, DisableUserinfoValidation.Descriptor, AttachAdditionalUserinfoRequestParameters.Descriptor, PopulateUserinfoTokenPrincipalFromTokenResponse.Descriptor, @@ -451,6 +452,59 @@ public static partial class OpenIddictClientWebIntegrationHandlers } } + /// + /// Contains the logic responsible for disabling the userinfo retrieval for the providers that require it. + /// + public sealed class DisableUserinfoRetrieval : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(EvaluateUserinfoRequest.Descriptor.Order + 250) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(ProcessAuthenticationContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + context.SendUserinfoRequest = context.Registration.ProviderName switch + { + // Note: the frontchannel or backchannel access tokens returned by Azure AD when a + // Xbox scope is requested cannot be used with the userinfo endpoint as they use a + // legacy format that is not supported by the Azure AD userinfo implementation. + // + // To work around this limitation, userinfo retrieval is disabled when a Xbox scope is requested. + Providers.Microsoft => context.GrantType switch + { + GrantTypes.AuthorizationCode or GrantTypes.Implicit when + context.StateTokenPrincipal is ClaimsPrincipal principal && + principal.HasClaim(static claim => + claim.Type is Claims.Private.Scope && + claim.Value.StartsWith("XboxLive.", StringComparison.OrdinalIgnoreCase)) + => false, + + GrantTypes.DeviceCode or GrantTypes.RefreshToken when + context.Scopes.Any(static scope => scope.StartsWith("XboxLive.", StringComparison.OrdinalIgnoreCase)) + => false, + + _ => context.SendUserinfoRequest + }, + + _ => context.SendUserinfoRequest + }; + + return default; + } + } + /// /// Contains the logic responsible for disabling the userinfo validation for the providers that require it. /// @@ -462,7 +516,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() .UseSingletonHandler() - .SetOrder(EvaluateUserinfoRequest.Descriptor.Order + 500) + .SetOrder(DisableUserinfoRetrieval.Descriptor.Order + 250) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build();