diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs index b841a0859..7a3a6cdd1 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs @@ -76,7 +76,7 @@ public ValueTask HandleAsync(PrepareUserInfoRequestContext context) // Attach the authorization header containing the access token to the HTTP request. request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, context.Request.AccessToken); - // Remove the access from the request payload to ensure it's not sent twice. + // Remove the access token from the request payload to ensure it's not sent twice. context.Request.AccessToken = null; return default; diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs index d3c614fb6..d99a5cb45 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Net.Http; +using System.Net.Http.Headers; using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlerFilters; using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers; using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants; @@ -17,12 +18,102 @@ public static partial class OpenIddictClientWebIntegrationHandlers public static class Revocation { public static ImmutableArray DefaultHandlers { get; } = ImmutableArray.Create([ + /* + * Revocation request preparation: + */ + OverrideHttpMethod.Descriptor, + AttachBearerAccessToken.Descriptor, + /* * Revocation response extraction: */ NormalizeContentType.Descriptor ]); + /// + /// Contains the logic responsible for overriding the HTTP method for the providers that require it. + /// + public sealed class OverrideHttpMethod : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .AddFilter() + .UseSingletonHandler() + .SetOrder(PreparePostHttpRequest.Descriptor.Order + 250) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(PrepareRevocationRequestContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved, + // this may indicate that the request was incorrectly processed by another client stack. + var request = context.Transaction.GetHttpRequestMessage() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0173)); + + request.Method = context.Registration.ProviderType switch + { + + ProviderTypes.Zendesk => HttpMethod.Delete, + + _ => request.Method + }; + + return default; + } + } + + /// + /// Contains the logic responsible for attaching the token to revoke + /// to the HTTP Authorization header for the providers that require it. + /// + public sealed class AttachBearerAccessToken : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .AddFilter() + .UseSingletonHandler() + .SetOrder(AttachHttpParameters.Descriptor.Order - 500) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(PrepareRevocationRequestContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved, + // this may indicate that the request was incorrectly processed by another client stack. + var request = context.Transaction.GetHttpRequestMessage() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0173)); + + // Zendesk requires using bearer authentication with the token that is going to be revoked. + if (context.Registration.ProviderType is ProviderTypes.Zendesk) + { + request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, context.Token); + + // Remove the token from the request payload to ensure it's not sent twice. + context.Request.Token = null; + } + + return default; + } + } + /// /// Contains the logic responsible for normalizing the returned content /// type of revocation responses for the providers that require it. diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs index 2457a3a82..ce73cae74 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs @@ -406,8 +406,9 @@ public ValueTask HandleAsync(ExtractUserInfoResponseContext context) ProviderTypes.ExactOnline => new(context.Response["d"]?["results"]?[0]?.GetNamedParameters() ?? throw new InvalidOperationException(SR.FormatID0334("d/results/0"))), - // Fitbit and Todoist return a nested "user" object. - ProviderTypes.Fitbit or ProviderTypes.Todoist => new(context.Response["user"]?.GetNamedParameters() ?? + // Fitbit, Todoist and Zendesk return a nested "user" object. + ProviderTypes.Fitbit or ProviderTypes.Todoist or ProviderTypes.Zendesk + => new(context.Response["user"]?.GetNamedParameters() ?? throw new InvalidOperationException(SR.FormatID0334("user"))), // Harvest returns a nested "user" object and a collection of "accounts". diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index 99f22ae2b..fc303c284 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -2153,6 +2153,35 @@ + + + + + + + + + + + + + +