|
|
|
@ -20,8 +20,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers |
|
|
|
*/ |
|
|
|
AmendIssuer.Descriptor, |
|
|
|
AmendGrantTypes.Descriptor, |
|
|
|
AmendTokenEndpointClientAuthenticationMethods.Descriptor, |
|
|
|
AmendCodeChallengeMethods.Descriptor, |
|
|
|
AmendScopes.Descriptor, |
|
|
|
AmendTokenEndpointClientAuthenticationMethods.Descriptor, |
|
|
|
AmendEndpoints.Descriptor); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -120,18 +121,18 @@ public static partial class OpenIddictClientWebIntegrationHandlers |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Contains the logic responsible for amending the client authentication
|
|
|
|
/// methods supported by the token endpoint for the providers that require it.
|
|
|
|
/// Contains the logic responsible for amending the supported
|
|
|
|
/// code challenge methods for the providers that require it.
|
|
|
|
/// </summary>
|
|
|
|
public sealed class AmendTokenEndpointClientAuthenticationMethods : IOpenIddictClientHandler<HandleConfigurationResponseContext> |
|
|
|
public sealed class AmendCodeChallengeMethods : IOpenIddictClientHandler<HandleConfigurationResponseContext> |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Gets the default descriptor definition assigned to this handler.
|
|
|
|
/// </summary>
|
|
|
|
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|
|
|
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleConfigurationResponseContext>() |
|
|
|
.UseSingletonHandler<AmendTokenEndpointClientAuthenticationMethods>() |
|
|
|
.SetOrder(ExtractTokenEndpointClientAuthenticationMethods.Descriptor.Order + 500) |
|
|
|
.UseSingletonHandler<AmendCodeChallengeMethods>() |
|
|
|
.SetOrder(ExtractCodeChallengeMethods.Descriptor.Order + 500) |
|
|
|
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
@ -143,17 +144,14 @@ public static partial class OpenIddictClientWebIntegrationHandlers |
|
|
|
throw new ArgumentNullException(nameof(context)); |
|
|
|
} |
|
|
|
|
|
|
|
// Apple implements a non-standard client authentication method for the token endpoint
|
|
|
|
// that is inspired by the standard private_key_jwt method but doesn't use the standard
|
|
|
|
// client_assertion/client_assertion_type parameters. Instead, the client assertion
|
|
|
|
// must be sent as a "dynamic" client secret using client_secret_post. Since the logic
|
|
|
|
// is the same as private_key_jwt, the configuration is amended to assume Apple supports
|
|
|
|
// private_key_jwt and an event handler is responsible for populating the client_secret
|
|
|
|
// parameter using the client assertion token once it has been generated by OpenIddict.
|
|
|
|
if (context.Registration.ProviderName is Providers.Apple) |
|
|
|
// Microsoft Account supports both the "plain" and "S256" code challenge methods but
|
|
|
|
// doesn't list them in the server configuration metadata. To ensure the OpenIddict
|
|
|
|
// client uses Proof Key for Code Exchange for the Microsoft provider, the 2 methods
|
|
|
|
// are manually added to the list of supported code challenge methods by this handler.
|
|
|
|
if (context.Registration.ProviderName is Providers.Microsoft) |
|
|
|
{ |
|
|
|
context.Configuration.TokenEndpointAuthMethodsSupported.Add( |
|
|
|
ClientAuthenticationMethods.PrivateKeyJwt); |
|
|
|
context.Configuration.CodeChallengeMethodsSupported.Add(CodeChallengeMethods.Plain); |
|
|
|
context.Configuration.CodeChallengeMethodsSupported.Add(CodeChallengeMethods.Sha256); |
|
|
|
} |
|
|
|
|
|
|
|
return default; |
|
|
|
@ -161,18 +159,17 @@ public static partial class OpenIddictClientWebIntegrationHandlers |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Contains the logic responsible for amending the supported
|
|
|
|
/// code challenge methods for the providers that require it.
|
|
|
|
/// Contains the logic responsible for amending the supported scopes for the providers that require it.
|
|
|
|
/// </summary>
|
|
|
|
public sealed class AmendCodeChallengeMethods : IOpenIddictClientHandler<HandleConfigurationResponseContext> |
|
|
|
public sealed class AmendScopes : IOpenIddictClientHandler<HandleConfigurationResponseContext> |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Gets the default descriptor definition assigned to this handler.
|
|
|
|
/// </summary>
|
|
|
|
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|
|
|
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleConfigurationResponseContext>() |
|
|
|
.UseSingletonHandler<AmendCodeChallengeMethods>() |
|
|
|
.SetOrder(ExtractCodeChallengeMethods.Descriptor.Order + 500) |
|
|
|
.UseSingletonHandler<AmendScopes>() |
|
|
|
.SetOrder(ExtractScopes.Descriptor.Order + 500) |
|
|
|
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
@ -184,14 +181,54 @@ public static partial class OpenIddictClientWebIntegrationHandlers |
|
|
|
throw new ArgumentNullException(nameof(context)); |
|
|
|
} |
|
|
|
|
|
|
|
// Microsoft Account supports both the "plain" and "S256" code challenge methods but
|
|
|
|
// doesn't list them in the server configuration metadata. To ensure the OpenIddict
|
|
|
|
// client uses Proof Key for Code Exchange for the Microsoft provider, the 2 methods
|
|
|
|
// are manually added to the list of supported code challenge methods by this handler.
|
|
|
|
if (context.Registration.ProviderName is Providers.Microsoft) |
|
|
|
// While it is a recommended node, Xero doesn't include "scopes_supported" in its server
|
|
|
|
// configuration and thus is treated as an OAuth 2.0-only provider by the OpenIddict client.
|
|
|
|
//
|
|
|
|
// To avoid that, the "openid" scope is manually added to indicate OpenID Connect is supported.
|
|
|
|
if (context.Registration.ProviderName is Providers.Xero) |
|
|
|
{ |
|
|
|
context.Configuration.CodeChallengeMethodsSupported.Add(CodeChallengeMethods.Plain); |
|
|
|
context.Configuration.CodeChallengeMethodsSupported.Add(CodeChallengeMethods.Sha256); |
|
|
|
context.Configuration.ScopesSupported.Add(Scopes.OpenId); |
|
|
|
} |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Contains the logic responsible for amending the client authentication
|
|
|
|
/// methods supported by the token endpoint for the providers that require it.
|
|
|
|
/// </summary>
|
|
|
|
public sealed class AmendTokenEndpointClientAuthenticationMethods : IOpenIddictClientHandler<HandleConfigurationResponseContext> |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Gets the default descriptor definition assigned to this handler.
|
|
|
|
/// </summary>
|
|
|
|
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|
|
|
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleConfigurationResponseContext>() |
|
|
|
.UseSingletonHandler<AmendTokenEndpointClientAuthenticationMethods>() |
|
|
|
.SetOrder(ExtractTokenEndpointClientAuthenticationMethods.Descriptor.Order + 500) |
|
|
|
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public ValueTask HandleAsync(HandleConfigurationResponseContext context) |
|
|
|
{ |
|
|
|
if (context is null) |
|
|
|
{ |
|
|
|
throw new ArgumentNullException(nameof(context)); |
|
|
|
} |
|
|
|
|
|
|
|
// Apple implements a non-standard client authentication method for the token endpoint
|
|
|
|
// that is inspired by the standard private_key_jwt method but doesn't use the standard
|
|
|
|
// client_assertion/client_assertion_type parameters. Instead, the client assertion
|
|
|
|
// must be sent as a "dynamic" client secret using client_secret_post. Since the logic
|
|
|
|
// is the same as private_key_jwt, the configuration is amended to assume Apple supports
|
|
|
|
// private_key_jwt and an event handler is responsible for populating the client_secret
|
|
|
|
// parameter using the client assertion token once it has been generated by OpenIddict.
|
|
|
|
if (context.Registration.ProviderName is Providers.Apple) |
|
|
|
{ |
|
|
|
context.Configuration.TokenEndpointAuthMethodsSupported.Add( |
|
|
|
ClientAuthenticationMethods.PrivateKeyJwt); |
|
|
|
} |
|
|
|
|
|
|
|
return default; |
|
|
|
|