diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
index 7349d8e7..5b13013e 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
@@ -8,6 +8,7 @@ using System.Collections.Immutable;
using System.Diagnostics;
using System.Text.Json;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlerFilters;
+using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers.Userinfo;
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
@@ -21,6 +22,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
/*
* Userinfo request preparation:
*/
+ AttachRequestHeaders.Descriptor,
AttachAccessTokenParameter.Descriptor,
/*
@@ -28,6 +30,50 @@ public static partial class OpenIddictClientWebIntegrationHandlers
*/
UnwrapUserinfoResponse.Descriptor);
+ ///
+ /// Contains the logic responsible for attaching additional
+ /// headers to the request for the providers that require it.
+ ///
+ public sealed class AttachRequestHeaders : IOpenIddictClientHandler
+ {
+ ///
+ /// Gets the default descriptor definition assigned to this handler.
+ ///
+ public static OpenIddictClientHandlerDescriptor Descriptor { get; }
+ = OpenIddictClientHandlerDescriptor.CreateBuilder()
+ .AddFilter()
+ .UseSingletonHandler()
+ .SetOrder(AttachUserAgentHeader.Descriptor.Order + 250)
+ .SetType(OpenIddictClientHandlerType.BuiltIn)
+ .Build();
+
+ ///
+ public ValueTask HandleAsync(PrepareUserinfoRequestContext context)
+ {
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
+ // this may indicate that the request was incorrectly processed by another client stack.
+ var request = context.Transaction.GetHttpRequestMessage() ??
+ throw new InvalidOperationException(SR.GetResourceString(SR.ID0173));
+
+ // Trakt requires sending both an API key (which is always the client identifier) and an API version
+ // (which is statically set to the last version known to be supported by the OpenIddict integration).
+ if (context.Registration.ProviderName is Providers.Trakt)
+ {
+ var options = context.Registration.GetTraktOptions();
+
+ request.Headers.Add("trakt-api-key", options.ClientId);
+ request.Headers.Add("trakt-api-version", "2");
+ }
+
+ return default;
+ }
+ }
+
///
/// Contains the logic responsible for attaching the access token
/// parameter to the request for the providers that require it.
@@ -62,11 +108,13 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// using the Bearer authentication scheme. Some providers don't support this method
// and require sending the access token as part of the userinfo request payload.
- if (context.Registration.ProviderName is Providers.Deezer or Providers.StackExchange)
+ (context.Request.AccessToken, request.Headers.Authorization) = context.Registration.ProviderName switch
{
- context.Request.AccessToken = request.Headers.Authorization?.Parameter;
- request.Headers.Authorization = null;
- }
+ Providers.Deezer or Providers.StackExchange
+ => (request.Headers.Authorization?.Parameter, null),
+
+ _ => (context.Request.AccessToken, request.Headers.Authorization)
+ };
return default;
}
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
index 205cd171..6419a409 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
@@ -238,13 +238,15 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// of the authorization requests, the value persisted in the state token principal
// MUST be replaced to include the state token received by the redirection endpoint.
- if (context.Registration.ProviderName is Providers.Deezer)
+ context.TokenRequest.RedirectUri = context.Registration.ProviderName switch
{
- context.TokenRequest.RedirectUri = OpenIddictHelpers.AddQueryStringParameter(
+ Providers.Deezer => OpenIddictHelpers.AddQueryStringParameter(
address: new Uri(context.TokenRequest.RedirectUri, UriKind.Absolute),
name: Parameters.State,
- value: context.StateToken).AbsoluteUri;
- }
+ value: context.StateToken).AbsoluteUri,
+
+ _ => context.TokenRequest.RedirectUri
+ };
return default;
}
@@ -338,6 +340,12 @@ public static partial class OpenIddictClientWebIntegrationHandlers
context.UserinfoRequest["site"] = options.Site;
}
+ // Trakt allows retrieving additional user details via the "extended" parameter.
+ else if (context.Registration.ProviderName is Providers.Trakt)
+ {
+ context.UserinfoRequest["extended"] = "full";
+ }
+
// Twitter limits the number of fields returned by the userinfo endpoint
// but allows returning additional information using special parameters that
// determine what fields will be returned as part of the userinfo response.
@@ -471,15 +479,15 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// Note: this workaround only works for providers that allow dynamic
// redirection URIs and implement a relaxed validation policy logic.
- if (context.Registration.ProviderName is Providers.Deezer)
+ (context.Request.RedirectUri, context.Request.State) = context.Registration.ProviderName switch
{
- context.Request.RedirectUri = OpenIddictHelpers.AddQueryStringParameter(
+ Providers.Deezer => (OpenIddictHelpers.AddQueryStringParameter(
address: new Uri(context.RedirectUri, UriKind.Absolute),
name: Parameters.State,
- value: context.Request.State).AbsoluteUri;
+ value: context.Request.State).AbsoluteUri, null),
- context.Request.State = null;
- }
+ _ => (context.Request.RedirectUri, context.Request.State)
+ };
return default;
}
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml
index b8075c98..cb24f5b9 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml
@@ -138,6 +138,14 @@
Description="The site specified in userinfo requests (by default, 'stackoverflow')" />
+
+
+
+
+
+