Browse Source

Change how additional userinfo parameters are handled by the Web providers

pull/1531/head
Kévin Chalet 4 years ago
parent
commit
41e4ef6bbc
  1. 59
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
  2. 44
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

59
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs

@ -7,8 +7,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text.Json;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers.Userinfo;
using static OpenIddict.Client.OpenIddictClientHandlers.Userinfo;
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
namespace OpenIddict.Client.WebIntegration;
@ -18,75 +17,29 @@ public static partial class OpenIddictClientWebIntegrationHandlers
public static class Userinfo
{
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create(
/*
* Userinfo request preparation:
*/
AttachAdditionalParameters.Descriptor,
/*
* Userinfo response extraction:
*/
UnwrapUserinfoResponse.Descriptor);
/// <summary>
/// Contains the logic responsible for attaching additional parameters for the providers that require it.
/// </summary>
public class AttachAdditionalParameters : IOpenIddictClientHandler<PrepareUserinfoRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.UseSingletonHandler<AttachAdditionalParameters>()
.SetOrder(PrepareGetHttpRequest<PrepareUserinfoRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(PrepareUserinfoRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Request is not null, SR.GetResourceString(SR.ID4008));
if (context.Registration.ProviderName is Providers.Twitter)
{
var options = context.Registration.GetTwitterOptions();
// 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.
context.Request["expansions"] = string.Join(",", options.Expansions);
context.Request["tweet.fields"] = string.Join(",", options.TweetFields);
context.Request["user.fields"] = string.Join(",", options.UserFields);
}
return default;
}
}
/// <summary>
/// Contains the logic responsible for extracting the userinfo response
/// from nested JSON nodes (e.g "data") for the providers that require it.
/// </summary>
public class UnwrapUserinfoResponse : IOpenIddictClientHandler<ExtractUserinfoResponseContext>
public class UnwrapUserinfoResponse : IOpenIddictClientHandler<HandleUserinfoResponseContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ExtractUserinfoResponseContext>()
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleUserinfoResponseContext>()
.UseSingletonHandler<UnwrapUserinfoResponse>()
.SetOrder(ExtractJsonHttpResponse<ExtractUserinfoResponseContext>.Descriptor.Order + 500)
.SetOrder(PopulateClaims.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ExtractUserinfoResponseContext context)
public ValueTask HandleAsync(HandleUserinfoResponseContext context)
{
if (context is null)
{
@ -102,7 +55,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
context.Response = context.Registration.ProviderName switch
{
// Twitter uses a nested object.
// Twitter returns a nested "data" object.
Providers.Twitter => (JsonElement) context.Response["data"]
is { ValueKind: JsonValueKind.Object } element ?
new(element) : throw new InvalidOperationException(SR.FormatID0334("data")),

44
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

@ -21,6 +21,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
*/
AttachNonStandardClientAssertionTokenClaims.Descriptor,
AttachTokenRequestNonStandardClientCredentials.Descriptor,
AttachAdditionalUserinfoRequestParameters.Descriptor,
/*
* Challenge processing:
@ -120,6 +121,49 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for attaching additional parameters
/// to the userinfo request for the providers that require it.
/// </summary>
public class AttachAdditionalUserinfoRequestParameters : IOpenIddictClientHandler<ProcessAuthenticationContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.AddFilter<RequireUserinfoRequest>()
.UseSingletonHandler<AttachAdditionalUserinfoRequestParameters>()
.SetOrder(AttachUserinfoRequestParameters.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.UserinfoRequest is not null, SR.GetResourceString(SR.ID4008));
if (context.Registration.ProviderName is Providers.Twitter)
{
var options = context.Registration.GetTwitterOptions();
// 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.
context.UserinfoRequest["expansions"] = string.Join(",", options.Expansions);
context.UserinfoRequest["tweet.fields"] = string.Join(",", options.TweetFields);
context.UserinfoRequest["user.fields"] = string.Join(",", options.UserFields);
}
return default;
}
}
/// <summary>
/// Contains the logic responsible for attaching a specific response mode for providers that require it.
/// </summary>

Loading…
Cancel
Save