Browse Source

Unify the attachment of HTTP parameters into a single event handler and add SubscribeStar to the list of supported providers

pull/1828/head
Kévin Chalet 3 years ago
parent
commit
8953e48b16
  1. 4
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs
  2. 4
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs
  3. 4
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs
  4. 4
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs
  5. 81
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  6. 4
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
  7. 98
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
  8. 9
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  9. 35
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml
  10. 4
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs
  11. 4
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs
  12. 81
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs

4
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Device.cs

@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
AttachUserAgentHeader<PrepareDeviceAuthorizationRequestContext>.Descriptor,
AttachFromHeader<PrepareDeviceAuthorizationRequestContext>.Descriptor,
AttachBasicAuthenticationCredentials.Descriptor,
AttachFormParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor,
AttachHttpParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor,
SendHttpRequest<ApplyDeviceAuthorizationRequestContext>.Descriptor,
DisposeHttpRequest<ApplyDeviceAuthorizationRequestContext>.Descriptor,
@ -52,7 +52,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareDeviceAuthorizationRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBasicAuthenticationCredentials>()
.SetOrder(AttachFormParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor.Order - 500)
.SetOrder(AttachHttpParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

4
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Discovery.cs

@ -22,7 +22,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
AttachJsonAcceptHeaders<PrepareConfigurationRequestContext>.Descriptor,
AttachUserAgentHeader<PrepareConfigurationRequestContext>.Descriptor,
AttachFromHeader<PrepareConfigurationRequestContext>.Descriptor,
AttachQueryStringParameters<PrepareConfigurationRequestContext>.Descriptor,
AttachHttpParameters<PrepareConfigurationRequestContext>.Descriptor,
SendHttpRequest<ApplyConfigurationRequestContext>.Descriptor,
DisposeHttpRequest<ApplyConfigurationRequestContext>.Descriptor,
@ -44,7 +44,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
AttachJsonAcceptHeaders<PrepareCryptographyRequestContext>.Descriptor,
AttachUserAgentHeader<PrepareCryptographyRequestContext>.Descriptor,
AttachFromHeader<PrepareCryptographyRequestContext>.Descriptor,
AttachQueryStringParameters<PrepareCryptographyRequestContext>.Descriptor,
AttachHttpParameters<PrepareCryptographyRequestContext>.Descriptor,
SendHttpRequest<ApplyCryptographyRequestContext>.Descriptor,
DisposeHttpRequest<ApplyCryptographyRequestContext>.Descriptor,

4
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs

@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
AttachUserAgentHeader<PrepareTokenRequestContext>.Descriptor,
AttachFromHeader<PrepareTokenRequestContext>.Descriptor,
AttachBasicAuthenticationCredentials.Descriptor,
AttachFormParameters<PrepareTokenRequestContext>.Descriptor,
AttachHttpParameters<PrepareTokenRequestContext>.Descriptor,
SendHttpRequest<ApplyTokenRequestContext>.Descriptor,
DisposeHttpRequest<ApplyTokenRequestContext>.Descriptor,
@ -52,7 +52,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBasicAuthenticationCredentials>()
.SetOrder(AttachFormParameters<PrepareTokenRequestContext>.Descriptor.Order - 500)
.SetOrder(AttachHttpParameters<PrepareTokenRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

4
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs

@ -27,7 +27,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
AttachUserAgentHeader<PrepareUserinfoRequestContext>.Descriptor,
AttachFromHeader<PrepareUserinfoRequestContext>.Descriptor,
AttachBearerAccessToken.Descriptor,
AttachQueryStringParameters<PrepareUserinfoRequestContext>.Descriptor,
AttachHttpParameters<PrepareUserinfoRequestContext>.Descriptor,
SendHttpRequest<ApplyUserinfoRequestContext>.Descriptor,
DisposeHttpRequest<ApplyUserinfoRequestContext>.Descriptor,
@ -53,7 +53,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBearerAccessToken>()
.SetOrder(AttachQueryStringParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 500)
.SetOrder(AttachHttpParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

81
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs

@ -316,9 +316,9 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
}
/// <summary>
/// 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.
/// </summary>
public sealed class AttachQueryStringParameters<TContext> : IOpenIddictClientHandler<TContext> where TContext : BaseExternalContext
public sealed class AttachHttpParameters<TContext> : IOpenIddictClientHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
/// 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<TContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.UseSingletonHandler<AttachHttpParameters<TContext>>()
#pragma warning disable CS0618
.SetOrder(AttachQueryStringParameters<TContext>.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<string?, string?>(parameter.Key, value));
}
return default;
}
}
/// <summary>
/// Contains the logic responsible for attaching the query string parameters to the HTTP request.
/// </summary>
[Obsolete("This class is obsolete and will be removed in a future version.")]
public sealed class AttachQueryStringParameters<TContext> : IOpenIddictClientHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context) => default;
}
/// <summary>
/// Contains the logic responsible for attaching the form parameters to the HTTP request.
/// </summary>
[Obsolete("This class is obsolete and will be removed in a future version.")]
public sealed class AttachFormParameters<TContext> : IOpenIddictClientHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
@ -377,29 +416,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
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<string?, string?>(parameter.Key, value));
return default;
}
public ValueTask HandleAsync(TContext context) => default;
}
/// <summary>

4
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs

@ -222,7 +222,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardQueryStringParameters>()
.SetOrder(AttachQueryStringParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetOrder(AttachHttpParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
@ -269,7 +269,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardRequestPayload>()
.SetOrder(AttachFormParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetOrder(AttachHttpParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

98
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);
/// <summary>
/// Contains the logic responsible for overriding the HTTP method for the providers that require it.
/// </summary>
public sealed class OverrideHttpMethod : IOpenIddictClientHandler<PrepareUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<OverrideHttpMethod>()
.SetOrder(PreparePostHttpRequest<PrepareUserinfoRequestContext>.Descriptor.Order + 250)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
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;
}
}
/// <summary>
/// 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<PrepareUserinfoRequestContext>()
.UseSingletonHandler<AttachNonStandardParameters>()
.SetOrder(AttachQueryStringParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 250)
.SetOrder(AttachHttpParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 250)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
@ -188,6 +232,54 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for attaching a non-standard payload for the providers that require it.
/// </summary>
public sealed class AttachNonStandardRequestPayload : IOpenIddictClientHandler<PrepareUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardRequestPayload>()
.SetOrder(AttachHttpParameters<PrepareUserinfoRequestContext>.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
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;
}
}
/// <summary>
/// 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<string, OpenIddictParameter>(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"))),

9
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)
{

35
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

@ -1060,6 +1060,39 @@
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ▄▄▄ ██ ██ ██ ▄▄▀██ ▄▄▄ ██ ▄▄▀██ ▄▄▀█▄ ▄██ ▄▄▀██ ▄▄▄██ ▄▄▄ █▄▄ ▄▄█ ▄▄▀██ ▄▄▀██
██▄▄▄▀▀██ ██ ██ ▄▄▀██▄▄▄▀▀██ █████ ▀▀▄██ ███ ▄▄▀██ ▄▄▄██▄▄▄▀▀███ ███ ▀▀ ██ ▀▀▄██
██ ▀▀▀ ██▄▀▀▄██ ▀▀ ██ ▀▀▀ ██ ▀▀▄██ ██ █▀ ▀██ ▀▀ ██ ▀▀▀██ ▀▀▀ ███ ███ ██ ██ ██ ██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->
<Provider Name="SubscribeStar" Id="1e6301aa-bef3-486a-b570-772d4918e749" Documentation="https://www.subscribestar.com/api">
<Environment Issuer="https://www.subscribestar.com/">
<Configuration AuthorizationEndpoint="https://www.subscribestar.com/oauth2/authorize"
TokenEndpoint="https://www.subscribestar.com/oauth2/token"
UserinfoEndpoint="https://www.subscribestar.com/api/graphql/v1">
<GrantType Value="authorization_code" />
<GrantType Value="refresh_token" />
</Configuration>
<!--
Note: SubscribeStar requires sending the "user.read" scope to be able to use the userinfo endpoint.
-->
<Scope Name="user.read" Default="true" Required="true" />
</Environment>
<Setting PropertyName="UserFields" ParameterName="fields" Collection="true" Type="String"
Description="The list of user fields to expand from the GraphQL endpoint (by default, only basic fields are requested)">
<Item Value="avatar_url" Default="true" Required="false" />
<Item Value="id" Default="true" Required="false" />
<Item Value="name" Default="true" Required="false" />
<Item Value="signed_up_at" Default="true" Required="false" />
</Setting>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ▄▄▄ ██ ██ ██ ▄▄ ██ ▄▄▄██ ▄▄▀██ ▄▄▄ ██ ▄▄▄██ ▄▄▄█▄ ▄██ ▄▄▀██ ▄▄▄██
@ -1120,7 +1153,7 @@
</Configuration>
<!--
Note: Trovo requires sending the "profile" scope to be able to use the userinfo endpoint.
Note: Trovo requires sending the "user_details_self" scope to be able to use the userinfo endpoint.
-->
<Scope Name="user_details_self" Default="true" Required="true" />

4
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Discovery.cs

@ -22,7 +22,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
AttachJsonAcceptHeaders<PrepareConfigurationRequestContext>.Descriptor,
AttachUserAgentHeader<PrepareConfigurationRequestContext>.Descriptor,
AttachFromHeader<PrepareConfigurationRequestContext>.Descriptor,
AttachQueryStringParameters<PrepareConfigurationRequestContext>.Descriptor,
AttachHttpParameters<PrepareConfigurationRequestContext>.Descriptor,
SendHttpRequest<ApplyConfigurationRequestContext>.Descriptor,
DisposeHttpRequest<ApplyConfigurationRequestContext>.Descriptor,
@ -44,7 +44,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
AttachJsonAcceptHeaders<PrepareCryptographyRequestContext>.Descriptor,
AttachUserAgentHeader<PrepareCryptographyRequestContext>.Descriptor,
AttachFromHeader<PrepareCryptographyRequestContext>.Descriptor,
AttachQueryStringParameters<PrepareCryptographyRequestContext>.Descriptor,
AttachHttpParameters<PrepareCryptographyRequestContext>.Descriptor,
SendHttpRequest<ApplyCryptographyRequestContext>.Descriptor,
DisposeHttpRequest<ApplyCryptographyRequestContext>.Descriptor,

4
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs

@ -27,7 +27,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
AttachUserAgentHeader<PrepareIntrospectionRequestContext>.Descriptor,
AttachFromHeader<PrepareIntrospectionRequestContext>.Descriptor,
AttachBasicAuthenticationCredentials.Descriptor,
AttachFormParameters<PrepareIntrospectionRequestContext>.Descriptor,
AttachHttpParameters<PrepareIntrospectionRequestContext>.Descriptor,
SendHttpRequest<ApplyIntrospectionRequestContext>.Descriptor,
DisposeHttpRequest<ApplyIntrospectionRequestContext>.Descriptor,
@ -52,7 +52,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
= OpenIddictValidationHandlerDescriptor.CreateBuilder<PrepareIntrospectionRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBasicAuthenticationCredentials>()
.SetOrder(AttachFormParameters<PrepareIntrospectionRequestContext>.Descriptor.Order - 500)
.SetOrder(AttachHttpParameters<PrepareIntrospectionRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build();

81
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs

@ -315,9 +315,9 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
}
/// <summary>
/// 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.
/// </summary>
public sealed class AttachQueryStringParameters<TContext> : IOpenIddictValidationHandler<TContext> where TContext : BaseExternalContext
public sealed class AttachHttpParameters<TContext> : IOpenIddictValidationHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
/// 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<TContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.UseSingletonHandler<AttachHttpParameters<TContext>>()
#pragma warning disable CS0618
.SetOrder(AttachQueryStringParameters<TContext>.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<string?, string?>(parameter.Key, value));
}
return default;
}
}
/// <summary>
/// Contains the logic responsible for attaching the query string parameters to the HTTP request.
/// </summary>
[Obsolete("This class is obsolete and will be removed in a future version.")]
public sealed class AttachQueryStringParameters<TContext> : IOpenIddictValidationHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context) => default;
}
/// <summary>
/// Contains the logic responsible for attaching the form parameters to the HTTP request.
/// </summary>
[Obsolete("This class is obsolete and will be removed in a future version.")]
public sealed class AttachFormParameters<TContext> : IOpenIddictValidationHandler<TContext> where TContext : BaseExternalContext
{
/// <summary>
@ -376,29 +415,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
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<string?, string?>(parameter.Key, value));
return default;
}
public ValueTask HandleAsync(TContext context) => default;
}
/// <summary>

Loading…
Cancel
Save