From 8953e48b163c7659f96b7e00bfa045f9d47a09e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Sat, 15 Jul 2023 18:17:58 +0200 Subject: [PATCH] Unify the attachment of HTTP parameters into a single event handler and add SubscribeStar to the list of supported providers --- ...ddictClientSystemNetHttpHandlers.Device.cs | 4 +- ...ctClientSystemNetHttpHandlers.Discovery.cs | 4 +- ...ictClientSystemNetHttpHandlers.Exchange.cs | 4 +- ...ictClientSystemNetHttpHandlers.Userinfo.cs | 4 +- .../OpenIddictClientSystemNetHttpHandlers.cs | 81 +++++++++------ ...ctClientWebIntegrationHandlers.Exchange.cs | 4 +- ...ctClientWebIntegrationHandlers.Userinfo.cs | 98 ++++++++++++++++++- .../OpenIddictClientWebIntegrationHandlers.cs | 9 ++ ...penIddictClientWebIntegrationProviders.xml | 35 ++++++- ...lidationSystemNetHttpHandlers.Discovery.cs | 4 +- ...tionSystemNetHttpHandlers.Introspection.cs | 4 +- ...enIddictValidationSystemNetHttpHandlers.cs | 81 +++++++++------ 12 files changed, 252 insertions(+), 80 deletions(-) diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs index d13a2ca5..ac12fb3a 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs @@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, AttachBasicAuthenticationCredentials.Descriptor, - AttachFormParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -52,7 +52,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachFormParameters.Descriptor.Order - 500) + .SetOrder(AttachHttpParameters.Descriptor.Order - 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs index e97be2d8..e0cb4048 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs @@ -22,7 +22,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers AttachJsonAcceptHeaders.Descriptor, AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, - AttachQueryStringParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -44,7 +44,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers AttachJsonAcceptHeaders.Descriptor, AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, - AttachQueryStringParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs index 0acbeae5..1684beee 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs @@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, AttachBasicAuthenticationCredentials.Descriptor, - AttachFormParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -52,7 +52,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachFormParameters.Descriptor.Order - 500) + .SetOrder(AttachHttpParameters.Descriptor.Order - 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs index b032e25e..5b62d929 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs @@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, AttachBearerAccessToken.Descriptor, - AttachQueryStringParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -53,7 +53,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachQueryStringParameters.Descriptor.Order - 500) + .SetOrder(AttachHttpParameters.Descriptor.Order - 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs index 07dfff47..281e15d7 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs @@ -316,9 +316,9 @@ public static partial class OpenIddictClientSystemNetHttpHandlers } /// - /// Contains the logic responsible for attaching the query string parameters to the HTTP request. + /// Contains the logic responsible for attaching the parameters to the HTTP request. /// - public sealed class AttachQueryStringParameters : IOpenIddictClientHandler where TContext : BaseExternalContext + public sealed class AttachHttpParameters : IOpenIddictClientHandler where TContext : BaseExternalContext { /// /// Gets the default descriptor definition assigned to this handler. @@ -326,8 +326,10 @@ public static partial class OpenIddictClientSystemNetHttpHandlers public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() - .UseSingletonHandler>() - .SetOrder(AttachFormParameters.Descriptor.Order - 1_000) + .UseSingletonHandler>() +#pragma warning disable CS0618 + .SetOrder(AttachQueryStringParameters.Descriptor.Order - 1_000) +#pragma warning restore CS0618 .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -346,23 +348,60 @@ public static partial class OpenIddictClientSystemNetHttpHandlers var request = context.Transaction.GetHttpRequestMessage() ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0173)); - if (request.RequestUri is null || context.Transaction.Request.Count is 0) + if (context.Transaction.Request.Count is 0) { return default; } - request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, - context.Transaction.Request.GetParameters().ToDictionary( - parameter => parameter.Key, - parameter => new StringValues((string?[]?) parameter.Value))); + // For GET requests, attach the request parameters to the query string by default. + if (request.Method == HttpMethod.Get && request.RequestUri is not null) + { + request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, + context.Transaction.Request.GetParameters().ToDictionary( + parameter => parameter.Key, + parameter => new StringValues((string?[]?) parameter.Value))); + } + + // For POST requests, attach the request parameters to the request form by default. + else if (request.Method == HttpMethod.Post) + { + request.Content = new FormUrlEncodedContent( + from parameter in context.Transaction.Request.GetParameters() + let values = (string?[]?) parameter.Value + where values is not null + from value in values + select new KeyValuePair(parameter.Key, value)); + } return default; } } + /// + /// Contains the logic responsible for attaching the query string parameters to the HTTP request. + /// + [Obsolete("This class is obsolete and will be removed in a future version.")] + public sealed class AttachQueryStringParameters : IOpenIddictClientHandler where TContext : BaseExternalContext + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .AddFilter() + .UseSingletonHandler>() + .SetOrder(AttachFormParameters.Descriptor.Order - 1_000) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(TContext context) => default; + } + /// /// Contains the logic responsible for attaching the form parameters to the HTTP request. /// + [Obsolete("This class is obsolete and will be removed in a future version.")] public sealed class AttachFormParameters : IOpenIddictClientHandler where TContext : BaseExternalContext { /// @@ -377,29 +416,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers .Build(); /// - public ValueTask HandleAsync(TContext context) - { - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - - Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008)); - - // 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.Content = new FormUrlEncodedContent( - from parameter in context.Transaction.Request.GetParameters() - let values = (string?[]?) parameter.Value - where values is not null - from value in values - select new KeyValuePair(parameter.Key, value)); - - return default; - } + public ValueTask HandleAsync(TContext context) => default; } /// diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs index 55d85315..d77a6a23 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs @@ -222,7 +222,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachQueryStringParameters.Descriptor.Order + 500) + .SetOrder(AttachHttpParameters.Descriptor.Order + 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -269,7 +269,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachFormParameters.Descriptor.Order + 500) + .SetOrder(AttachHttpParameters.Descriptor.Order + 500) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs index 84f4c88f..04b1720c 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs @@ -8,6 +8,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Http.Json; using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpConstants; using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlerFilters; using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers; @@ -24,9 +25,11 @@ public static partial class OpenIddictClientWebIntegrationHandlers /* * Userinfo request preparation: */ + OverrideHttpMethod.Descriptor, AttachRequestHeaders.Descriptor, AttachAccessTokenParameter.Descriptor, AttachNonStandardParameters.Descriptor, + AttachNonStandardRequestPayload.Descriptor, /* * Userinfo response extraction: @@ -34,6 +37,47 @@ public static partial class OpenIddictClientWebIntegrationHandlers NormalizeContentType.Descriptor, UnwrapUserinfoResponse.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(PrepareUserinfoRequestContext 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 + { + // SubscribeStar's userinfo implementation is based on GraphQL, which requires using POST. + ProviderTypes.SubscribeStar => HttpMethod.Post, + + _ => request.Method + }; + + return default; + } + } + /// /// Contains the logic responsible for attaching additional /// headers to the request for the providers that require it. @@ -165,7 +209,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() .UseSingletonHandler() - .SetOrder(AttachQueryStringParameters.Descriptor.Order - 250) + .SetOrder(AttachHttpParameters.Descriptor.Order - 250) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -188,6 +232,54 @@ public static partial class OpenIddictClientWebIntegrationHandlers } } + /// + /// Contains the logic responsible for attaching a non-standard payload for the providers that require it. + /// + public sealed class AttachNonStandardRequestPayload : 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(PrepareUserinfoRequestContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008)); + + // 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.Content = context.Registration.ProviderType switch + { + // SubscribeStar's userinfo implementation is based on GraphQL, + // which requires sending the request parameters as a JSON payload. + ProviderTypes.SubscribeStar => JsonContent.Create(context.Transaction.Request, + new MediaTypeHeaderValue(MediaTypes.Json) + { + CharSet = Charsets.Utf8 + }), + + _ => request.Content + }; + + return default; + } + } + /// /// Contains the logic responsible for normalizing the returned content /// type of userinfo responses for the providers that require it. @@ -317,6 +409,10 @@ public static partial class OpenIddictClientWebIntegrationHandlers let name = $"{parameter.Key}_{node.Key}" select new KeyValuePair(name, node.Value)), + // SubscribeStar returns a nested "user" object that is itself nested in a GraphQL "data" node. + ProviderTypes.SubscribeStar => new(context.Response["data"]?["user"]?.GetNamedParameters() ?? + throw new InvalidOperationException(SR.FormatID0334("data/user"))), + // Tumblr returns a nested "user" object that is itself nested in a "response" node. ProviderTypes.Tumblr => new(context.Response["response"]?["user"]?.GetNamedParameters() ?? throw new InvalidOperationException(SR.FormatID0334("response/user"))), diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index b40e8332..9fdad597 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -802,6 +802,15 @@ public static partial class OpenIddictClientWebIntegrationHandlers context.UserinfoRequest["site"] = settings.Site; } + // SubscribeStar's userinfo endpoint is a GraphQL implementation that requires + // sending a proper "query" parameter containing the requested user details. + else if (context.Registration.ProviderType is ProviderTypes.SubscribeStar) + { + var settings = context.Registration.GetSubscribeStarSettings(); + + context.UserinfoRequest["query"] = $"{{ user {{ {string.Join(", ", settings.UserFields)} }} }}"; + } + // Trakt allows retrieving additional user details via the "extended" parameter. else if (context.Registration.ProviderType is ProviderTypes.Trakt) { diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index 45ed3f5b..f03a6011 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -1060,6 +1060,39 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs index 7ad104db..bc7b7522 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs @@ -22,7 +22,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers AttachJsonAcceptHeaders.Descriptor, AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, - AttachQueryStringParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -44,7 +44,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers AttachJsonAcceptHeaders.Descriptor, AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, - AttachQueryStringParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs index 83d17599..e3d48fc1 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs @@ -27,7 +27,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers AttachUserAgentHeader.Descriptor, AttachFromHeader.Descriptor, AttachBasicAuthenticationCredentials.Descriptor, - AttachFormParameters.Descriptor, + AttachHttpParameters.Descriptor, SendHttpRequest.Descriptor, DisposeHttpRequest.Descriptor, @@ -52,7 +52,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() - .SetOrder(AttachFormParameters.Descriptor.Order - 500) + .SetOrder(AttachHttpParameters.Descriptor.Order - 500) .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs index 7fff8104..58f48b4f 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs @@ -315,9 +315,9 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers } /// - /// Contains the logic responsible for attaching the query string parameters to the HTTP request. + /// Contains the logic responsible for attaching the parameters to the HTTP request. /// - public sealed class AttachQueryStringParameters : IOpenIddictValidationHandler where TContext : BaseExternalContext + public sealed class AttachHttpParameters : IOpenIddictValidationHandler where TContext : BaseExternalContext { /// /// Gets the default descriptor definition assigned to this handler. @@ -325,8 +325,10 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers public static OpenIddictValidationHandlerDescriptor Descriptor { get; } = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() - .UseSingletonHandler>() - .SetOrder(AttachFormParameters.Descriptor.Order - 1_000) + .UseSingletonHandler>() +#pragma warning disable CS0618 + .SetOrder(AttachQueryStringParameters.Descriptor.Order - 1_000) +#pragma warning restore CS0618 .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); @@ -345,23 +347,60 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers var request = context.Transaction.GetHttpRequestMessage() ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0173)); - if (request.RequestUri is null || context.Transaction.Request.Count is 0) + if (context.Transaction.Request.Count is 0) { return default; } - request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, - context.Transaction.Request.GetParameters().ToDictionary( - parameter => parameter.Key, - parameter => new StringValues((string?[]?) parameter.Value))); + // For GET requests, attach the request parameters to the query string by default. + if (request.Method == HttpMethod.Get && request.RequestUri is not null) + { + request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, + context.Transaction.Request.GetParameters().ToDictionary( + parameter => parameter.Key, + parameter => new StringValues((string?[]?) parameter.Value))); + } + + // For POST requests, attach the request parameters to the request form by default. + else if (request.Method == HttpMethod.Post) + { + request.Content = new FormUrlEncodedContent( + from parameter in context.Transaction.Request.GetParameters() + let values = (string?[]?) parameter.Value + where values is not null + from value in values + select new KeyValuePair(parameter.Key, value)); + } return default; } } + /// + /// Contains the logic responsible for attaching the query string parameters to the HTTP request. + /// + [Obsolete("This class is obsolete and will be removed in a future version.")] + public sealed class AttachQueryStringParameters : IOpenIddictValidationHandler where TContext : BaseExternalContext + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictValidationHandlerDescriptor Descriptor { get; } + = OpenIddictValidationHandlerDescriptor.CreateBuilder() + .AddFilter() + .UseSingletonHandler>() + .SetOrder(AttachFormParameters.Descriptor.Order - 1_000) + .SetType(OpenIddictValidationHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(TContext context) => default; + } + /// /// Contains the logic responsible for attaching the form parameters to the HTTP request. /// + [Obsolete("This class is obsolete and will be removed in a future version.")] public sealed class AttachFormParameters : IOpenIddictValidationHandler where TContext : BaseExternalContext { /// @@ -376,29 +415,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers .Build(); /// - public ValueTask HandleAsync(TContext context) - { - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - - Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008)); - - // 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.Content = new FormUrlEncodedContent( - from parameter in context.Transaction.Request.GetParameters() - let values = (string?[]?) parameter.Value - where values is not null - from value in values - select new KeyValuePair(parameter.Key, value)); - - return default; - } + public ValueTask HandleAsync(TContext context) => default; } ///