|
68 | 68 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; |
69 | 69 | import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; |
70 | 70 | import org.springframework.security.oauth2.jose.TestJwks; |
| 71 | +import org.springframework.security.oauth2.jose.jws.MacAlgorithm; |
71 | 72 | import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; |
72 | 73 | import org.springframework.security.oauth2.jwt.JwsHeader; |
73 | 74 | import org.springframework.security.oauth2.jwt.Jwt; |
|
103 | 104 | import org.springframework.test.web.servlet.MvcResult; |
104 | 105 | import org.springframework.web.util.UriComponentsBuilder; |
105 | 106 |
|
| 107 | +import javax.crypto.spec.SecretKeySpec; |
| 108 | + |
106 | 109 | import static org.assertj.core.api.Assertions.assertThat; |
107 | 110 | import static org.hamcrest.CoreMatchers.containsString; |
108 | 111 | import static org.mockito.ArgumentMatchers.any; |
@@ -400,6 +403,55 @@ public void requestWhenClientRegistersWithSecretThenClientAuthenticationSuccess( |
400 | 403 | .andReturn(); |
401 | 404 | } |
402 | 405 |
|
| 406 | + // gh-1344 |
| 407 | + @Test |
| 408 | + public void requestWhenClientRegistersWithClientSecretJwtThenClientAuthenticationSuccess() throws Exception { |
| 409 | + this.spring.register(AuthorizationServerConfiguration.class).autowire(); |
| 410 | + |
| 411 | + // @formatter:off |
| 412 | + OidcClientRegistration clientRegistration = OidcClientRegistration.builder() |
| 413 | + .clientName("client-name") |
| 414 | + .redirectUri("https://client.example.com") |
| 415 | + .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) |
| 416 | + .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) |
| 417 | + .tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT.getValue()) |
| 418 | + .scope("scope1") |
| 419 | + .scope("scope2") |
| 420 | + .build(); |
| 421 | + // @formatter:on |
| 422 | + |
| 423 | + OidcClientRegistration clientRegistrationResponse = registerClient(clientRegistration); |
| 424 | + |
| 425 | + JwsHeader jwsHeader = JwsHeader.with(MacAlgorithm.HS256) |
| 426 | + .build(); |
| 427 | + |
| 428 | + Instant issuedAt = Instant.now(); |
| 429 | + Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); |
| 430 | + JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder() |
| 431 | + .issuer(clientRegistrationResponse.getClientId()) |
| 432 | + .subject(clientRegistrationResponse.getClientId()) |
| 433 | + .audience(Collections.singletonList(asUrl(this.authorizationServerSettings.getIssuer(), this.authorizationServerSettings.getTokenEndpoint()))) |
| 434 | + .issuedAt(issuedAt) |
| 435 | + .expiresAt(expiresAt) |
| 436 | + .build(); |
| 437 | + |
| 438 | + JWKSet jwkSet = new JWKSet(TestJwks.jwk( |
| 439 | + new SecretKeySpec(clientRegistrationResponse.getClientSecret().getBytes(), "HS256")).build()); |
| 440 | + JwtEncoder jwtClientAssertionEncoder = new NimbusJwtEncoder((jwkSelector, securityContext) -> jwkSelector.select(jwkSet)); |
| 441 | + |
| 442 | + Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet)); |
| 443 | + |
| 444 | + this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) |
| 445 | + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) |
| 446 | + .param(OAuth2ParameterNames.SCOPE, "scope1") |
| 447 | + .param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") |
| 448 | + .param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue()) |
| 449 | + .param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId())) |
| 450 | + .andExpect(status().isOk()) |
| 451 | + .andExpect(jsonPath("$.access_token").isNotEmpty()) |
| 452 | + .andExpect(jsonPath("$.scope").value("scope1")); |
| 453 | + } |
| 454 | + |
403 | 455 | private OidcClientRegistration registerClient(OidcClientRegistration clientRegistration) throws Exception { |
404 | 456 | // ***** (1) Obtain the "initial" access token used for registering the client |
405 | 457 |
|
|
0 commit comments