|
23 | 23 | import java.util.UUID; |
24 | 24 | import java.util.function.Consumer; |
25 | 25 |
|
| 26 | +import javax.crypto.spec.SecretKeySpec; |
| 27 | + |
26 | 28 | import com.nimbusds.jose.jwk.JWKSet; |
27 | 29 | import com.nimbusds.jose.jwk.source.JWKSource; |
28 | 30 | import com.nimbusds.jose.proc.SecurityContext; |
@@ -406,6 +408,55 @@ public void requestWhenClientRegistersWithSecretThenClientAuthenticationSuccess( |
406 | 408 | .andReturn(); |
407 | 409 | } |
408 | 410 |
|
| 411 | + // gh-1344 |
| 412 | + @Test |
| 413 | + public void requestWhenClientRegistersWithClientSecretJwtThenClientAuthenticationSuccess() throws Exception { |
| 414 | + this.spring.register(AuthorizationServerConfiguration.class).autowire(); |
| 415 | + |
| 416 | + // @formatter:off |
| 417 | + OidcClientRegistration clientRegistration = OidcClientRegistration.builder() |
| 418 | + .clientName("client-name") |
| 419 | + .redirectUri("https://client.example.com") |
| 420 | + .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) |
| 421 | + .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) |
| 422 | + .tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT.getValue()) |
| 423 | + .scope("scope1") |
| 424 | + .scope("scope2") |
| 425 | + .build(); |
| 426 | + // @formatter:on |
| 427 | + |
| 428 | + OidcClientRegistration clientRegistrationResponse = registerClient(clientRegistration); |
| 429 | + |
| 430 | + JwsHeader jwsHeader = JwsHeader.with(MacAlgorithm.HS256) |
| 431 | + .build(); |
| 432 | + |
| 433 | + Instant issuedAt = Instant.now(); |
| 434 | + Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); |
| 435 | + JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder() |
| 436 | + .issuer(clientRegistrationResponse.getClientId()) |
| 437 | + .subject(clientRegistrationResponse.getClientId()) |
| 438 | + .audience(Collections.singletonList(asUrl(this.authorizationServerSettings.getIssuer(), this.authorizationServerSettings.getTokenEndpoint()))) |
| 439 | + .issuedAt(issuedAt) |
| 440 | + .expiresAt(expiresAt) |
| 441 | + .build(); |
| 442 | + |
| 443 | + JWKSet jwkSet = new JWKSet(TestJwks.jwk( |
| 444 | + new SecretKeySpec(clientRegistrationResponse.getClientSecret().getBytes(), "HS256")).build()); |
| 445 | + JwtEncoder jwtClientAssertionEncoder = new NimbusJwtEncoder((jwkSelector, securityContext) -> jwkSelector.select(jwkSet)); |
| 446 | + |
| 447 | + Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet)); |
| 448 | + |
| 449 | + this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) |
| 450 | + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) |
| 451 | + .param(OAuth2ParameterNames.SCOPE, "scope1") |
| 452 | + .param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") |
| 453 | + .param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue()) |
| 454 | + .param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId())) |
| 455 | + .andExpect(status().isOk()) |
| 456 | + .andExpect(jsonPath("$.access_token").isNotEmpty()) |
| 457 | + .andExpect(jsonPath("$.scope").value("scope1")); |
| 458 | + } |
| 459 | + |
409 | 460 | @Test |
410 | 461 | public void requestWhenClientRegistersWithCustomMetadataThenSavedToRegisteredClient() throws Exception { |
411 | 462 | this.spring.register(CustomClientMetadataConfiguration.class).autowire(); |
|
0 commit comments