diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs
index 4b5e5929..8597c291 100644
--- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs
+++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs
@@ -32,7 +32,7 @@ public sealed class OpenIddictClientSystemNetHttpBuilder
public IServiceCollection Services { get; }
///
- /// Amends the default OpenIddict client/server integration configuration.
+ /// Amends the default OpenIddict client/System.Net.Http configuration.
///
/// The delegate used to configure the OpenIddict options.
/// This extension can be safely called multiple times.
@@ -49,6 +49,138 @@ public sealed class OpenIddictClientSystemNetHttpBuilder
return this;
}
+ ///
+ /// Configures the used by the OpenIddict client/System.Net.Http integration.
+ ///
+ ///
+ /// Note: customizations configured using this method apply to all providers.
+ ///
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictClientSystemNetHttpBuilder ConfigureHttpClient(Action configuration)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options =>
+ {
+ if (options.HttpClientActions.TryGetValue(string.Empty, out var actions))
+ {
+ actions.Add(configuration);
+ }
+
+ else
+ {
+ options.HttpClientActions[string.Empty] = new(capacity: 1) { configuration };
+ }
+ });
+ }
+
+ ///
+ /// Configures the used by the OpenIddict client/System.Net.Http integration.
+ ///
+ ///
+ /// Note: customizations configured using this method only apply to the specified provider.
+ ///
+ /// The provider name, to which the customizations are applied.
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictClientSystemNetHttpBuilder ConfigureHttpClient(string provider, Action configuration)
+ {
+ if (string.IsNullOrEmpty(provider))
+ {
+ throw new ArgumentException(SR.FormatID0366(nameof(provider)), nameof(provider));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options =>
+ {
+ if (options.HttpClientActions.TryGetValue(provider, out var actions))
+ {
+ actions.Add(configuration);
+ }
+
+ else
+ {
+ options.HttpClientActions[provider] = new(capacity: 1) { configuration };
+ }
+ });
+ }
+
+ ///
+ /// Configures the used by the OpenIddict client/System.Net.Http integration.
+ ///
+ ///
+ /// Note: customizations configured using this method apply to all providers.
+ ///
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictClientSystemNetHttpBuilder ConfigureHttpClientHandler(Action configuration)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options =>
+ {
+ if (options.HttpClientHandlerActions.TryGetValue(string.Empty, out var actions))
+ {
+ actions.Add(configuration);
+ }
+
+ else
+ {
+ options.HttpClientHandlerActions[string.Empty] = new(capacity: 1) { configuration };
+ }
+ });
+ }
+
+ ///
+ /// Configures the used by the OpenIddict client/System.Net.Http integration.
+ ///
+ ///
+ /// Note: customizations configured using this method only apply to the specified provider.
+ ///
+ /// The provider name, to which the customizations are applied.
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictClientSystemNetHttpBuilder ConfigureHttpClientHandler(string provider, Action configuration)
+ {
+ if (string.IsNullOrEmpty(provider))
+ {
+ throw new ArgumentException(SR.FormatID0366(nameof(provider)), nameof(provider));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options =>
+ {
+ if (options.HttpClientHandlerActions.TryGetValue(provider, out var actions))
+ {
+ actions.Add(configuration);
+ }
+
+ else
+ {
+ options.HttpClientHandlerActions[provider] = new(capacity: 1) { configuration };
+ }
+ });
+ }
+
///
/// Sets the contact address used in the "From" header that is attached
/// to the backchannel HTTP requests sent to the authorization server.
diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs
index 2ca70f6b..036f3821 100644
--- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs
+++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs
@@ -19,7 +19,6 @@ namespace OpenIddict.Client.SystemNetHttp;
public sealed class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptions,
IConfigureNamedOptions
{
-#if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
private readonly IServiceProvider _provider;
///
@@ -28,7 +27,6 @@ public sealed class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptio
/// The service provider.
public OpenIddictClientSystemNetHttpConfiguration(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
-#endif
///
public void Configure(OpenIddictClientOptions options)
@@ -60,15 +58,26 @@ public sealed class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptio
return;
}
- options.HttpClientActions.Add(options =>
+ var settings = _provider.GetRequiredService>().CurrentValue;
+
+ options.HttpClientActions.Add(client =>
{
// By default, HttpClient uses a default timeout of 100 seconds and allows payloads of up to 2GB.
// To help reduce the effects of malicious responses (e.g responses returned at a very slow pace
// or containing an infine amount of data), the default values are amended to use lower values.
- options.MaxResponseContentBufferSize = 10 * 1024 * 1024;
- options.Timeout = TimeSpan.FromMinutes(1);
+ client.MaxResponseContentBufferSize = 10 * 1024 * 1024;
+ client.Timeout = TimeSpan.FromMinutes(1);
});
+ // Register the user-defined HTTP client actions.
+ foreach (var action in settings.HttpClientActions
+ .Where(action => string.IsNullOrEmpty(action.Key) || // Note: actions that have an empty key apply to all providers.
+ action.Key.AsSpan().Equals(name.AsSpan(assembly.Name!.Length + 1), StringComparison.Ordinal))
+ .SelectMany(action => action.Value))
+ {
+ options.HttpClientActions.Add(action);
+ }
+
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
#if SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
@@ -98,5 +107,15 @@ public sealed class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptio
builder.AdditionalHandlers.Add(new PolicyHttpMessageHandler(policy));
}
});
+
+ // Register the user-defined HTTP client handler actions.
+ foreach (var action in settings.HttpClientHandlerActions
+ .Where(action => string.IsNullOrEmpty(action.Key) || // Note: actions that have an empty key apply to all providers.
+ action.Key.AsSpan().Equals(name.AsSpan(assembly.Name!.Length + 1), StringComparison.Ordinal))
+ .SelectMany(action => action.Value))
+ {
+ options.HttpMessageHandlerBuilderActions.Add(builder => action(builder.PrimaryHandler as HttpClientHandler ??
+ throw new InvalidOperationException(SR.FormatID0373(typeof(HttpClientHandler).FullName))));
+ }
}
}
diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpOptions.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpOptions.cs
index 9a0d7d1f..d393314c 100644
--- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpOptions.cs
+++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpOptions.cs
@@ -36,4 +36,16 @@ public sealed class OpenIddictClientSystemNetHttpOptions
/// attached to the backchannel HTTP requests sent to the authorization server.
///
public ProductInfoHeaderValue? ProductInformation { get; set; }
+
+ ///
+ /// Gets the user-defined actions used to amend the
+ /// instances created by the OpenIddict client/System.Net.Http integration.
+ ///
+ public Dictionary>> HttpClientActions { get; } = new();
+
+ ///
+ /// Gets the user-defined actions used to amend the
+ /// instances created by the OpenIddict client/System.Net.Http integration.
+ ///
+ public Dictionary>> HttpClientHandlerActions { get; } = new();
}
diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs
index 209c2e88..d6a88253 100644
--- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs
+++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs
@@ -32,7 +32,7 @@ public sealed class OpenIddictValidationSystemNetHttpBuilder
public IServiceCollection Services { get; }
///
- /// Amends the default OpenIddict validation/server integration configuration.
+ /// Amends the default OpenIddict validation/System.Net.Http configuration.
///
/// The delegate used to configure the OpenIddict options.
/// This extension can be safely called multiple times.
@@ -49,6 +49,38 @@ public sealed class OpenIddictValidationSystemNetHttpBuilder
return this;
}
+ ///
+ /// Configures the used by the OpenIddict validation/System.Net.Http integration.
+ ///
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictValidationSystemNetHttpBuilder ConfigureHttpClient(Action configuration)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options => options.HttpClientActions.Add(configuration));
+ }
+
+ ///
+ /// Configures the used by the OpenIddict client/System.Net.Http integration.
+ ///
+ /// The delegate used to configure the .
+ /// The instance.
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public OpenIddictValidationSystemNetHttpBuilder ConfigureHttpClientHandler(Action configuration)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ return Configure(options => options.HttpClientHandlerActions.Add(configuration));
+ }
+
///
/// Sets the contact address used in the "From" header that is attached
/// to the backchannel HTTP requests sent to the authorization server.
diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs
index 9ec617f4..139ee8d2 100644
--- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs
+++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs
@@ -19,7 +19,6 @@ namespace OpenIddict.Validation.SystemNetHttp;
public sealed class OpenIddictValidationSystemNetHttpConfiguration : IConfigureOptions,
IConfigureNamedOptions
{
-#if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
private readonly IServiceProvider _provider;
///
@@ -28,7 +27,6 @@ public sealed class OpenIddictValidationSystemNetHttpConfiguration : IConfigureO
/// The service provider.
public OpenIddictValidationSystemNetHttpConfiguration(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
-#endif
///
public void Configure(OpenIddictValidationOptions options)
@@ -60,15 +58,23 @@ public sealed class OpenIddictValidationSystemNetHttpConfiguration : IConfigureO
return;
}
- options.HttpClientActions.Add(options =>
+ var settings = _provider.GetRequiredService>().CurrentValue;
+
+ options.HttpClientActions.Add(client =>
{
// By default, HttpClient uses a default timeout of 100 seconds and allows payloads of up to 2GB.
// To help reduce the effects of malicious responses (e.g responses returned at a very slow pace
// or containing an infine amount of data), the default values are amended to use lower values.
- options.MaxResponseContentBufferSize = 10 * 1024 * 1024;
- options.Timeout = TimeSpan.FromMinutes(1);
+ client.MaxResponseContentBufferSize = 10 * 1024 * 1024;
+ client.Timeout = TimeSpan.FromMinutes(1);
});
+ // Register the user-defined HTTP client actions.
+ foreach (var action in settings.HttpClientActions)
+ {
+ options.HttpClientActions.Add(action);
+ }
+
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
#if SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
@@ -98,5 +104,12 @@ public sealed class OpenIddictValidationSystemNetHttpConfiguration : IConfigureO
builder.AdditionalHandlers.Add(new PolicyHttpMessageHandler(policy));
}
});
+
+ // Register the user-defined HTTP client handler actions.
+ foreach (var action in settings.HttpClientHandlerActions)
+ {
+ options.HttpMessageHandlerBuilderActions.Add(builder => action(builder.PrimaryHandler as HttpClientHandler ??
+ throw new InvalidOperationException(SR.FormatID0373(typeof(HttpClientHandler).FullName))));
+ }
}
}
diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs
index d50946c6..a03ed869 100644
--- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs
+++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs
@@ -36,4 +36,16 @@ public sealed class OpenIddictValidationSystemNetHttpOptions
/// attached to the backchannel HTTP requests sent to the authorization server.
///
public ProductInfoHeaderValue? ProductInformation { get; set; }
+
+ ///
+ /// Gets the user-defined actions used to amend the
+ /// instances created by the OpenIddict validation/System.Net.Http integration.
+ ///
+ public List> HttpClientActions { get; } = new();
+
+ ///
+ /// Gets the user-defined actions used to amend the
+ /// instances created by the OpenIddict validation/System.Net.Http integration.
+ ///
+ public List> HttpClientHandlerActions { get; } = new();
}