diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs index 3caab7e6f..3e22bf095 100644 --- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs +++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs @@ -39,6 +39,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers */ WaitMarshalledAuthentication.Descriptor, + RestoreRequestFromMarshalledContext.Descriptor, RestoreClientRegistrationFromMarshalledContext.Descriptor, EvaluateValidatedUpfrontTokensForMarshalledContext.Descriptor, @@ -661,6 +662,48 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context) } } + /// + /// Contains the logic responsible for restoring the request from the marshalled authentication context, if applicable. + /// + public sealed class RestoreRequestFromMarshalledContext : IOpenIddictClientHandler + { + private readonly OpenIddictClientSystemIntegrationMarshal _marshal; + + public RestoreRequestFromMarshalledContext(OpenIddictClientSystemIntegrationMarshal marshal) + => _marshal = marshal ?? throw new ArgumentNullException(nameof(marshal)); + + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .AddFilter() + .UseSingletonHandler() + .SetOrder(WaitMarshalledAuthentication.Descriptor.Order + 250) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(ProcessAuthenticationContext context) + { + ArgumentNullException.ThrowIfNull(context); + + Debug.Assert(!string.IsNullOrEmpty(context.Nonce), SR.GetResourceString(SR.ID4019)); + + context.Request = context.EndpointType switch + { + // When the authentication demand is marshalled from a different context, restore the request from the + // other instance so that custom parameters can be resolved from the marshalled context, if necessary. + OpenIddictClientEndpointType.Unknown when _marshal.TryGetResult(context.Nonce, out var notification) + => notification.Request, + + _ => context.Request + }; + + return ValueTask.CompletedTask; + } + } + /// /// Contains the logic responsible for restoring the client registration and /// configuration from the marshalled authentication context, if applicable. diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index 346aaaff8..8d2b8609a 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -524,7 +524,7 @@ ProviderTypes.Trovo when context.GrantType is GrantTypes.RefreshToken // For more information, see // https://www.zoho.com/accounts/protocol/oauth/multi-dc/client-authorization.html. ProviderTypes.Zoho when context.GrantType is GrantTypes.AuthorizationCode - => ((string?) context.Request?["location"])?.ToUpperInvariant() switch + => ((string?) context.Request["location"])?.ToUpperInvariant() switch { "AU" => new Uri("https://accounts.zoho.com.au/oauth/v2/token", UriKind.Absolute), "CA" => new Uri("https://accounts.zohocloud.ca/oauth/v2/token", UriKind.Absolute), @@ -1077,7 +1077,7 @@ ProviderTypes.SuperOffice when // For more information, see // https://www.zoho.com/accounts/protocol/oauth/multi-dc/client-authorization.html. ProviderTypes.Zoho when context.GrantType is GrantTypes.AuthorizationCode - => ((string?) context.Request?["location"])?.ToUpperInvariant() switch + => ((string?) context.Request["location"])?.ToUpperInvariant() switch { "AU" => new Uri("https://accounts.zoho.com.au/oauth/user/info", UriKind.Absolute), "CA" => new Uri("https://accounts.zohocloud.ca/oauth/user/info", UriKind.Absolute), diff --git a/src/OpenIddict.Client/OpenIddictClientService.cs b/src/OpenIddict.Client/OpenIddictClientService.cs index 3ee95b891..cc58d4955 100644 --- a/src/OpenIddict.Client/OpenIddictClientService.cs +++ b/src/OpenIddict.Client/OpenIddictClientService.cs @@ -272,6 +272,7 @@ public async ValueTask AuthenticateInteractivel { CancellationToken = request.CancellationToken, Nonce = request.Nonce, + Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new() @@ -430,6 +431,7 @@ public async ValueTask AuthenticateWithCl Issuer = request.Issuer, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, + Request = new(), TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new() }; @@ -521,6 +523,7 @@ GrantTypes.DeviceCode or GrantTypes.Implicit or GrantType = request.GrantType, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, + Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new() @@ -616,6 +619,7 @@ public async ValueTask AuthenticateWithDeviceAsync(D Issuer = request.Issuer, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, + Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new() @@ -801,6 +805,7 @@ public async ValueTask AuthenticateWithPasswordAsy Password = request.Password, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, + Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new(), @@ -889,6 +894,7 @@ public async ValueTask AuthenticateWithTokenE Issuer = request.Issuer, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, + Request = new(), RequestedTokenType = request.RequestedTokenType, SubjectToken = request.SubjectToken, SubjectTokenType = request.SubjectTokenType, @@ -975,6 +981,7 @@ public async ValueTask AuthenticateWithRefresh ProviderName = request.ProviderName, RefreshToken = request.RefreshToken, RegistrationId = request.RegistrationId, + Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenRequest = request.AdditionalTokenRequestParameters is Dictionary parameters ? new(parameters) : new()