Skip to content

Commit 927f3b9

Browse files
committed
Add client_secret_jwt support
1 parent 0441377 commit 927f3b9

File tree

3 files changed

+53
-20
lines changed

3 files changed

+53
-20
lines changed

identity-server/src/Configuration/Validation/DynamicClientRegistration/DynamicClientRegistrationValidator.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ protected virtual Task<IStepResult> SetGrantTypesAsync(DynamicClientRegistration
153153

154154
if (context.Request.GrantTypes.Contains(OidcConstants.GrantTypes.RefreshToken))
155155
{
156-
// Note that if we ever support additional grant types that allow refresh tokens, this
156+
// Note that if we ever support additional grant types that allow refresh tokens, this
157157
// could be refactored.
158158
if (!context.Client.AllowedGrantTypes.Contains(GrantType.AuthorizationCode))
159159
{
@@ -302,7 +302,7 @@ protected virtual Task<IStepResult> SetDefaultScopes(DynamicClientRegistrationCo
302302
}
303303

304304
/// <summary>
305-
/// Validates the requested jwks to set the secrets of the client.
305+
/// Validates the requested jwks to set the secrets of the client.
306306
/// </summary>
307307
/// <param name="context">The dynamic client registration context, which
308308
/// includes the client model that will have its secrets set, the DCR
@@ -317,9 +317,11 @@ protected virtual Task<IStepResult> SetSecretsAsync(DynamicClientRegistrationCon
317317
return StepResult.Failure("The jwks_uri and jwks parameters must not be used together");
318318
}
319319

320-
if (context.Request.Jwks is null && context.Request.TokenEndpointAuthenticationMethod == OidcConstants.EndpointAuthenticationMethods.PrivateKeyJwt)
320+
if (context.Request.Jwks is null &&
321+
context.Request.TokenEndpointAuthenticationMethod is
322+
OidcConstants.EndpointAuthenticationMethods.PrivateKeyJwt or "client_secret_jwt")
321323
{
322-
return StepResult.Failure("Missing jwks parameter - the private_key_jwt token_endpoint_auth_method requires the jwks parameter");
324+
return StepResult.Failure($"Missing jwks parameter - the {context.Request.TokenEndpointAuthenticationMethod} token_endpoint_auth_method requires the jwks parameter");
323325

324326
}
325327
if (context.Request.Jwks is not null)
@@ -571,7 +573,7 @@ protected virtual Task<IStepResult> SetServerSideSessionProperties(DynamicClient
571573
/// Validates details of the request that control the user interface,
572574
/// including the logo uri, client uri, initiate login uri, enable local
573575
/// login flag, and identity provider restrictions, and uses them to set the
574-
/// corresponding client properties.
576+
/// corresponding client properties.
575577
/// </summary>
576578
/// <param name="context">The dynamic client registration context, which
577579
/// includes the client model that will have miscellaneous properties set,

identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,22 @@ where scope.ShowInDiscoveryDocument
326326
types.Add(OidcConstants.EndpointAuthenticationMethods.TlsClientAuth);
327327
types.Add(OidcConstants.EndpointAuthenticationMethods.SelfSignedTlsClientAuth);
328328
}
329-
entries.Add(OidcConstants.Discovery.TokenEndpointAuthenticationMethodsSupported, types);
330-
331329
if (types.Contains(OidcConstants.EndpointAuthenticationMethods.PrivateKeyJwt) &&
332330
!IEnumerableExtensions.IsNullOrEmpty(Options.SupportedClientAssertionSigningAlgorithms))
333331
{
334332
entries.Add(OidcConstants.Discovery.TokenEndpointAuthSigningAlgorithmsSupported,
335333
Options.SupportedClientAssertionSigningAlgorithms);
334+
if (Options.SupportedClientAssertionSigningAlgorithms.Any(alg => alg.StartsWith("HS")))
335+
{
336+
types.Add("client_secret_jwt");
337+
}
338+
339+
if (Options.SupportedClientAssertionSigningAlgorithms.All(alg => alg.StartsWith("HS")))
340+
{
341+
types.Remove("private_key_jwt");
342+
}
336343
}
344+
entries.Add(OidcConstants.Discovery.TokenEndpointAuthenticationMethodsSupported, types);
337345
}
338346

339347
var signingCredentials = await Keys.GetAllSigningCredentialsAsync();

identity-server/test/IdentityServer.IntegrationTests/Endpoints/Discovery/DiscoveryEndpointTests_token_endpoint_auth_signing_algs_supported.cs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,53 @@
1010

1111
namespace IntegrationTests.Endpoints.Discovery;
1212

13-
public class DiscoveryEndpointTests_token_endpoint_auth_signing_alg_values_supported
13+
public class DiscoveryEndpointTests_token_endpoint_auth
1414
{
15-
private const string Category = "Discovery endpoint - token_endpoint_auth_signing_alg_values_supported";
15+
private const string Category = "Discovery endpoint - token_endpoint_auth";
1616

17-
[Fact]
17+
[Theory]
1818
[Trait("Category", Category)]
19-
public async Task token_endpoint_auth_signing_alg_values_supported_should_match_configuration()
19+
[InlineData(true, true, SecurityAlgorithms.RsaSha256, SecurityAlgorithms.HmacSha256)]
20+
[InlineData(true, true, SecurityAlgorithms.RsaSsaPssSha384, SecurityAlgorithms.HmacSha384)]
21+
[InlineData(true, true, SecurityAlgorithms.EcdsaSha512, SecurityAlgorithms.HmacSha512)]
22+
[InlineData(false, true, SecurityAlgorithms.HmacSha256)]
23+
[InlineData(false, true, SecurityAlgorithms.HmacSha384)]
24+
[InlineData(false, true, SecurityAlgorithms.HmacSha512)]
25+
[InlineData(true, false, SecurityAlgorithms.RsaSha256)]
26+
[InlineData(true, false, SecurityAlgorithms.RsaSha384)]
27+
[InlineData(true, false, SecurityAlgorithms.RsaSha512)]
28+
[InlineData(true, false, SecurityAlgorithms.RsaSsaPssSha256)]
29+
[InlineData(true, false, SecurityAlgorithms.RsaSsaPssSha384)]
30+
[InlineData(true, false, SecurityAlgorithms.RsaSsaPssSha512)]
31+
[InlineData(true, false, SecurityAlgorithms.EcdsaSha256)]
32+
[InlineData(true, false, SecurityAlgorithms.EcdsaSha384)]
33+
[InlineData(true, false, SecurityAlgorithms.EcdsaSha512)]
34+
35+
public async Task token_endpoint_auth_should_match_configuration(bool privateKeyJwtExpected, bool clientSecretJwtExpected, params string[] algorithms)
2036
{
37+
// This test verifies that the algorithms supported match the configured algorithms, and that
38+
// the supported auth methods are appropriate for the algorithms
2139
var pipeline = new IdentityServerPipeline();
2240
pipeline.OnPostConfigureServices += svcs =>
2341
svcs.AddIdentityServerBuilder().AddJwtBearerClientAuthentication();
2442
pipeline.Initialize();
25-
pipeline.Options.SupportedClientAssertionSigningAlgorithms =
26-
[
27-
SecurityAlgorithms.RsaSsaPssSha256,
28-
SecurityAlgorithms.EcdsaSha256
29-
];
43+
pipeline.Options.SupportedClientAssertionSigningAlgorithms = algorithms;
3044

3145
var disco = await pipeline.BackChannelClient
3246
.GetDiscoveryDocumentAsync("https://server/.well-known/openid-configuration");
3347
disco.IsError.ShouldBeFalse();
3448

3549
var algorithmsSupported = disco.TokenEndpointAuthenticationSigningAlgorithmsSupported;
3650

37-
algorithmsSupported.Count().ShouldBe(2);
38-
algorithmsSupported.ShouldContain(SecurityAlgorithms.RsaSsaPssSha256);
39-
algorithmsSupported.ShouldContain(SecurityAlgorithms.EcdsaSha256);
51+
algorithmsSupported.Count().ShouldBe(algorithms.Length);
52+
foreach (var algorithm in algorithms)
53+
{
54+
algorithmsSupported.ShouldContain(algorithm);
55+
}
56+
57+
var authMethods = disco.TokenEndpointAuthenticationMethodsSupported;
58+
authMethods.Contains("private_key_jwt").ShouldBe(privateKeyJwtExpected);
59+
authMethods.Contains("client_secret_jwt").ShouldBe(clientSecretJwtExpected);
4060
}
4161

4262
[Fact]
@@ -68,6 +88,10 @@ await pipeline.BackChannelClient.GetDiscoveryDocumentAsync(
6888
algorithmsSupported.ShouldContain(SecurityAlgorithms.HmacSha256);
6989
algorithmsSupported.ShouldContain(SecurityAlgorithms.HmacSha384);
7090
algorithmsSupported.ShouldContain(SecurityAlgorithms.HmacSha512);
91+
92+
var authMethods = result.TokenEndpointAuthenticationMethodsSupported;
93+
authMethods.ShouldContain("private_key_jwt");
94+
authMethods.ShouldContain("client_secret_jwt");
7195
}
7296

7397
[Fact]
@@ -84,7 +108,6 @@ public async Task token_endpoint_auth_signing_alg_values_supported_should_not_be
84108
// Verify assumptions
85109
disco.IsError.ShouldBeFalse();
86110
disco.TokenEndpointAuthenticationMethodsSupported.ShouldNotContain("private_key_jwt");
87-
// we don't even support client_secret_jwt, but per spec, if you DO, you must include the algs supported
88111
disco.TokenEndpointAuthenticationMethodsSupported.ShouldNotContain("client_secret_jwt");
89112

90113
// Assert that we got no signing algs.

0 commit comments

Comments
 (0)