From 6a86b45ddc52e6826faba6a58ed940704992413e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 13 Oct 2022 19:23:30 +0200 Subject: [PATCH] Add StackExchange support --- ...ctClientWebIntegrationHandlers.Userinfo.cs | 54 +++++++++++++++++++ .../OpenIddictClientWebIntegrationHandlers.cs | 10 +++- ...penIddictClientWebIntegrationProviders.xml | 14 +++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs index f8dc287b..e8e7955f 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.OpenIddictClientHandlers.Userinfo; +using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers.Userinfo; using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants; namespace OpenIddict.Client.WebIntegration; @@ -17,11 +18,59 @@ public static partial class OpenIddictClientWebIntegrationHandlers public static class Userinfo { public static ImmutableArray DefaultHandlers { get; } = ImmutableArray.Create( + /* + * Userinfo request preparation: + */ + AttachAccessTokenParameter.Descriptor, + /* * Userinfo response extraction: */ UnwrapUserinfoResponse.Descriptor); + /// + /// Contains the logic responsible for attaching the access token + /// parameter to the request for the providers that require it. + /// + public class AttachAccessTokenParameter : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(AttachBearerAccessToken.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)); + + // By default, OpenIddict sends the access token as part of the Authorization header + // 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.StackExchange) + { + context.Request.AccessToken = request.Headers.Authorization?.Parameter; + request.Headers.Authorization = null; + } + + return default; + } + } + /// /// Contains the logic responsible for extracting the userinfo response /// from nested JSON nodes (e.g "data") for the providers that require it. @@ -55,6 +104,11 @@ public static partial class OpenIddictClientWebIntegrationHandlers context.Response = context.Registration.ProviderName switch { + // StackExchange returns an "items" array containing a single element. + Providers.StackExchange => (JsonElement) context.Response["items"] + is { ValueKind: JsonValueKind.Array } element && element.GetArrayLength() is 1 ? + new(element[0]) : throw new InvalidOperationException(SR.FormatID0334("items")), + // Twitter returns a nested "data" object. Providers.Twitter => (JsonElement) context.Response["data"] is { ValueKind: JsonValueKind.Object } element ? diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index dfc6b803..0756ba75 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -148,7 +148,15 @@ public static partial class OpenIddictClientWebIntegrationHandlers Debug.Assert(context.UserinfoRequest is not null, SR.GetResourceString(SR.ID4008)); - if (context.Registration.ProviderName is Providers.Twitter) + if (context.Registration.ProviderName is Providers.StackExchange) + { + var options = context.Registration.GetStackExchangeOptions(); + + context.UserinfoRequest["key"] = options.ApplicationKey; + context.UserinfoRequest["site"] = options.Site; + } + + else if (context.Registration.ProviderName is Providers.Twitter) { var options = context.Registration.GetTwitterOptions(); diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index be271390..6ba621ff 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -58,6 +58,20 @@ + + + + + + + + + +