From 5a02224f34c9b4efd21dae55dc563c369f8c1905 Mon Sep 17 00:00:00 2001 From: OpenIddict Bot <32257313+openiddict-bot@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:46:50 +0000 Subject: [PATCH] Update the documentation pages --- guides/contributing-a-new-web-provider.html | 59 ++++++++++++++++++++- manifest.json | 2 +- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/guides/contributing-a-new-web-provider.html b/guides/contributing-a-new-web-provider.html index 1104af8..a63b980 100644 --- a/guides/contributing-a-new-web-provider.html +++ b/guides/contributing-a-new-web-provider.html @@ -218,7 +218,64 @@ store the tenant name. Once added, the URIs can include a placeholder of the sam Description="The tenant used to identify the Zendesk instance" /> </Provider> -

Test the generated provider

+

If the provider doesn't support standard OpenID Connect userinfo, map the provider-specific claims to their ClaimTypes equivalent

+

If the provider doesn't return an id_token and doesn't offer a standard userinfo endpoint, it is likely it uses custom parameters +to represent things like the user identifier. If so, update the MapCustomWebServicesFederationClaims event handler to map these +parameters to the usual WS-Federation claims exposed by the .NET BCL ClaimTypes class, which simplifies integration with libraries +like ASP.NET Core Identity:

+
/// <summary>
+/// Contains the logic responsible for mapping select custom claims to
+/// their WS-Federation equivalent for the providers that require it.
+/// </summary>
+public sealed class MapCustomWebServicesFederationClaims : IOpenIddictClientHandler<ProcessAuthenticationContext>
+{
+    /// <summary>
+    /// Gets the default descriptor definition assigned to this handler.
+    /// </summary>
+    public static OpenIddictClientHandlerDescriptor Descriptor { get; }
+        = OpenIddictClientHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
+            .AddFilter<RequireWebServicesFederationClaimMappingEnabled>()
+            .UseSingletonHandler<MapCustomWebServicesFederationClaims>()
+            .SetOrder(MapStandardWebServicesFederationClaims.Descriptor.Order + 1_000)
+            .SetType(OpenIddictClientHandlerType.BuiltIn)
+            .Build();
+
+    /// <inheritdoc/>
+    public ValueTask HandleAsync(ProcessAuthenticationContext context)
+    {
+        if (context is null)
+        {
+            throw new ArgumentNullException(nameof(context));
+        }
+
+        context.MergedPrincipal.SetClaim(ClaimTypes.Email, context.Registration.ProviderType switch
+        {
+            // ServiceChannel returns the user identifier as a custom "Email" node:
+            ProviderTypes.ServiceChannel => (string?) context.UserinfoResponse?["Email"],
+
+            _ => context.MergedPrincipal.GetClaim(ClaimTypes.Email)
+        });
+
+        context.MergedPrincipal.SetClaim(ClaimTypes.Name, context.Registration.ProviderType switch
+        {
+            // ServiceChannel returns the user identifier as a custom "UserName" node:
+            ProviderTypes.ServiceChannel => (string?) context.UserinfoResponse?["UserName"],
+
+            _ => context.MergedPrincipal.GetClaim(ClaimTypes.Name)
+        });
+
+        context.MergedPrincipal.SetClaim(ClaimTypes.NameIdentifier, context.Registration.ProviderType switch
+        {
+            // ServiceChannel returns the user identifier as a custom "UserId" node:
+            ProviderTypes.ServiceChannel => (string?) context.UserinfoResponse?["UserId"],
+
+            _ => context.MergedPrincipal.GetClaim(ClaimTypes.NameIdentifier)
+        });
+
+        return default;
+    }
+}
+

Test the generated provider

If the targeted service is fully standard-compliant, no additional configuration should be required at this point. To confirm it, build the solution and add an instance of the new provider to the OpenIddict.Sandbox.AspNetCore.Client sandbox: