From 3a7d09ecff68c4b68f4d80438686c770557cb8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 9 Jun 2025 23:59:10 +0200 Subject: [PATCH] Update the Apple integration to force using the generic "JWT" type for client assertions --- ...ClientWebIntegrationHandlers.Protection.cs | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Protection.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Protection.cs index 3f09df24..a3304d6c 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Protection.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Protection.cs @@ -19,7 +19,12 @@ public static partial class OpenIddictClientWebIntegrationHandlers /* * Token validation: */ - AmendTokenValidationParameters.Descriptor + AmendTokenValidationParameters.Descriptor, + + /* + * Token generation: + */ + AmendSecurityTokenDescriptor.Descriptor ]; /// @@ -79,5 +84,54 @@ public static partial class OpenIddictClientWebIntegrationHandlers return default; } } + + /// + /// Contains the logic responsible for amending the security token descriptor for the providers that require it. + /// + public sealed class AmendSecurityTokenDescriptor : IOpenIddictClientHandler + { + /// + /// Gets the default descriptor definition assigned to this handler. + /// + public static OpenIddictClientHandlerDescriptor Descriptor { get; } + = OpenIddictClientHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(AttachTokenMetadata.Descriptor.Order + 500) + .SetType(OpenIddictClientHandlerType.BuiltIn) + .Build(); + + /// + public ValueTask HandleAsync(GenerateTokenContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + // Note: the client registration may be null (e.g when generating a state token). + // In this case, don't amend the default security token descriptor. + if (context.Registration is null) + { + return default; + } + + context.SecurityTokenDescriptor.TokenType = context.Registration.ProviderType switch + { + // Note: Apple implements a non-standard client authentication method for its endpoints that + // is inspired by the standard private_key_jwt method but doesn't use the standard parameters. + // OpenIddict 7.0+ no longer uses the generic "JWT" type for client assertions by default and + // uses the new standard "client-authentication+jwt" type instead. While Apple currently ignores + // the JSON Web Token "typ" header (making this change non-breaking), the generic "JWT" value + // is deliberately used for the Apple provider to avoid a potential issue in case their "dynamic + // client secret" validation logic would be updated to require using the generic "JWT" value. + ProviderTypes.Apple when context.TokenType is TokenTypeIdentifiers.Private.ClientAssertion + => JsonWebTokenTypes.GenericJsonWebToken, + + _ => context.SecurityTokenDescriptor.TokenType + }; + + return default; + } + } } }