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()