Browse Source

Add Pro Santé Connect to the list of supported providers

pull/1640/head
Kévin Chalet 3 years ago
parent
commit
11c5b7ee9e
  1. 77
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs
  2. 4
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs
  3. 10
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  4. 22
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

77
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs

@ -5,7 +5,12 @@
*/
using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options;
using OpenIddict.Client.SystemNetHttp;
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
namespace OpenIddict.Client.WebIntegration;
@ -13,8 +18,20 @@ namespace OpenIddict.Client.WebIntegration;
/// Contains the methods required to ensure that the OpenIddict client Web integration configuration is valid.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public sealed partial class OpenIddictClientWebIntegrationConfiguration : IConfigureOptions<OpenIddictClientOptions>
public sealed partial class OpenIddictClientWebIntegrationConfiguration : IConfigureOptions<OpenIddictClientOptions>,
IConfigureNamedOptions<HttpClientFactoryOptions>
{
#if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
private readonly IServiceProvider _provider;
/// <summary>
/// Creates a new instance of the <see cref="OpenIddictClientWebIntegrationConfiguration"/> class.
/// </summary>
/// <param name="provider">The service provider.</param>
public OpenIddictClientWebIntegrationConfiguration(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
#endif
/// <inheritdoc/>
public void Configure(OpenIddictClientOptions options)
{
@ -26,4 +43,62 @@ public sealed partial class OpenIddictClientWebIntegrationConfiguration : IConfi
// Register the built-in event handlers used by the OpenIddict client Web components.
options.Handlers.AddRange(OpenIddictClientWebIntegrationHandlers.DefaultHandlers);
}
/// <inheritdoc/>
public void Configure(HttpClientFactoryOptions options) => Configure(Options.DefaultName, options);
/// <inheritdoc/>
public void Configure(string? name, HttpClientFactoryOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
// Only amend the HTTP client factory options if the instance is managed by OpenIddict
// and contains the name of a provider managed by OpenIddict.Client.WebIntegration.
var assembly = typeof(OpenIddictClientSystemNetHttpOptions).Assembly.GetName();
if (string.IsNullOrEmpty(name) || !name.StartsWith(assembly.Name!, StringComparison.Ordinal) ||
name.Length < assembly.Name!.Length + 1 || name[assembly.Name.Length] is not ':')
{
return;
}
// Note: while not enforced yet, Pro Santé Connect's specification requires sending a TLS
// client certificate when communicating with its backchannel OpenID Connect endpoints.
//
// For that, the primary HTTP handler must be altered or replaced by an instance that
// includes the client certificate set in the options in its certificate collection.
//
// For more information, see EXI PSC 24 in the annex part of
// https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000045551195.
if (name.AsSpan(assembly.Name.Length + 1) is Providers.ProSantéConnect)
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
// Note: the client registration instance is not available here,
// so the provider options must be resolved via the DI container.
#if SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
var options = builder.Services.GetRequiredService<IOptionsMonitor<
OpenIddictClientWebIntegrationOptions.ProSantéConnect>>().CurrentValue;
#else
var options = _provider.GetRequiredService<IOptionsMonitor<
OpenIddictClientWebIntegrationOptions.ProSantéConnect>>().CurrentValue;
#endif
// If a client certificate was specified, alter the HTTP handler.
if (options.ClientCertificate is X509Certificate certificate)
{
// If the primary HTTP handler is not an instance of HttpClientHandler, replace it by
// a new instance of HttpClientHandler as it required to attach the client certificate.
if (builder.PrimaryHandler is not HttpClientHandler handler)
{
builder.PrimaryHandler = handler = new HttpClientHandler();
}
handler.ClientCertificates.Add(certificate);
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
}
});
}
}
}

4
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs

@ -5,6 +5,7 @@
*/
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options;
using OpenIddict.Client;
using OpenIddict.Client.WebIntegration;
@ -40,7 +41,8 @@ public static class OpenIddictClientWebIntegrationExtensions
// Note: TryAddEnumerable() is used here to ensure the initializers are registered only once.
builder.Services.TryAddEnumerable(new[]
{
ServiceDescriptor.Singleton<IConfigureOptions<OpenIddictClientOptions>, OpenIddictClientWebIntegrationConfiguration>()
ServiceDescriptor.Singleton<IConfigureOptions<OpenIddictClientOptions>, OpenIddictClientWebIntegrationConfiguration>(),
ServiceDescriptor.Singleton<IConfigureOptions<HttpClientFactoryOptions>, OpenIddictClientWebIntegrationConfiguration>()
});
return new OpenIddictClientWebIntegrationBuilder(builder.Services);

10
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

@ -545,6 +545,16 @@ public static partial class OpenIddictClientWebIntegrationHandlers
context.Request["access_type"] = options.AccessType;
}
// Pro Santé Connect's specification requires sending an acr_values parameter containing
// the desired level of authentication (currently, only "eidas1" is supported). For more
// information, see https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000045551195.
else if (context.Registration.ProviderName is Providers.ProSantéConnect)
{
var options = context.Registration.GetProSantéConnectOptions();
context.Request.AcrValues = options.AuthenticationLevel;
}
// By default, Reddit doesn't return a refresh token but
// allows sending a "duration" parameter to retrieve one.
else if (context.Registration.ProviderName is Providers.Reddit)

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

@ -130,6 +130,28 @@
<Environment Name="Sandbox" Issuer="https://www.paypal.com/" />
</Provider>
<Provider Name="ProSantéConnect" Documentation="https://industriels.esante.gouv.fr/en/products-services/health-pro-authentication-pro-sante-connect">
<!--
Note: Pro Santé Connect requires sending the "scope_all" scope (which is currently the only supported value).
-->
<Environment Name="Production" Issuer="https://auth.esw.esante.gouv.fr/auth/realms/esante-wallet"
ConfigurationEndpoint="https://auth.esw.esante.gouv.fr/auth/realms/esante-wallet/.well-known/wallet-openid-configuration">
<Scope Name="scope_all" Default="true" Required="true" />
</Environment>
<Environment Name="Sandbox" Issuer="https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet"
ConfigurationEndpoint="https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet/.well-known/wallet-openid-configuration">
<Scope Name="scope_all" Default="true" Required="true" />
</Environment>
<Setting PropertyName="AuthenticationLevel" ParameterName="level" Type="String" Required="true" DefaultValue="eidas1"
Description="The level of authentication requested, sent as part of the 'acr_values' parameter (by default, 'eidas1')" />
<Setting PropertyName="ClientCertificate" ParameterName="certificate" Type="Certificate" Required="false"
Description="The TLS client certificate that will be used with the backchannel endpoints (while not enforced yet, its use is strongly recommended)" />
</Provider>
<Provider Name="Reddit" Documentation="https://github.com/reddit-archive/reddit/wiki/OAuth2">
<Environment Issuer="https://www.reddit.com/">
<Configuration AuthorizationEndpoint="https://www.reddit.com/api/v1/authorize"

Loading…
Cancel
Save