@@ -19,7 +19,12 @@ public static class Protection
1919 /*
2020 * Token validation:
2121 */
22- AmendTokenValidationParameters . Descriptor
22+ AmendTokenValidationParameters . Descriptor ,
23+
24+ /*
25+ * Token generation:
26+ */
27+ AmendSecurityTokenDescriptor . Descriptor
2328 ] ;
2429
2530 /// <summary>
@@ -79,5 +84,54 @@ ProviderTypes.Microsoft when
7984 return default ;
8085 }
8186 }
87+
88+ /// <summary>
89+ /// Contains the logic responsible for amending the security token descriptor for the providers that require it.
90+ /// </summary>
91+ public sealed class AmendSecurityTokenDescriptor : IOpenIddictClientHandler < GenerateTokenContext >
92+ {
93+ /// <summary>
94+ /// Gets the default descriptor definition assigned to this handler.
95+ /// </summary>
96+ public static OpenIddictClientHandlerDescriptor Descriptor { get ; }
97+ = OpenIddictClientHandlerDescriptor . CreateBuilder < GenerateTokenContext > ( )
98+ . UseSingletonHandler < AmendSecurityTokenDescriptor > ( )
99+ . SetOrder ( AttachTokenMetadata . Descriptor . Order + 500 )
100+ . SetType ( OpenIddictClientHandlerType . BuiltIn )
101+ . Build ( ) ;
102+
103+ /// <inheritdoc/>
104+ public ValueTask HandleAsync ( GenerateTokenContext context )
105+ {
106+ if ( context is null )
107+ {
108+ throw new ArgumentNullException ( nameof ( context ) ) ;
109+ }
110+
111+ // Note: the client registration may be null (e.g when generating a state token).
112+ // In this case, don't amend the default security token descriptor.
113+ if ( context . Registration is null )
114+ {
115+ return default ;
116+ }
117+
118+ context . SecurityTokenDescriptor . TokenType = context . Registration . ProviderType switch
119+ {
120+ // Note: Apple implements a non-standard client authentication method for its endpoints that
121+ // is inspired by the standard private_key_jwt method but doesn't use the standard parameters.
122+ // OpenIddict 7.0+ no longer uses the generic "JWT" type for client assertions by default and
123+ // uses the new standard "client-authentication+jwt" type instead. While Apple currently ignores
124+ // the JSON Web Token "typ" header (making this change non-breaking), the generic "JWT" value
125+ // is deliberately used for the Apple provider to avoid a potential issue in case their "dynamic
126+ // client secret" validation logic would be updated to require using the generic "JWT" value.
127+ ProviderTypes . Apple when context . TokenType is TokenTypeIdentifiers . Private . ClientAssertion
128+ => JsonWebTokenTypes . GenericJsonWebToken ,
129+
130+ _ => context . SecurityTokenDescriptor . TokenType
131+ } ;
132+
133+ return default ;
134+ }
135+ }
82136 }
83137}
0 commit comments