@ -68,6 +68,7 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResp
@@ -68,6 +68,7 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResp
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames ;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter ;
import org.springframework.security.oauth2.jose.TestJwks ;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm ;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm ;
import org.springframework.security.oauth2.jwt.JwsHeader ;
import org.springframework.security.oauth2.jwt.Jwt ;
@ -103,6 +104,8 @@ import org.springframework.test.web.servlet.MockMvc;
@@ -103,6 +104,8 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult ;
import org.springframework.web.util.UriComponentsBuilder ;
import javax.crypto.spec.SecretKeySpec ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.hamcrest.CoreMatchers.containsString ;
import static org.mockito.ArgumentMatchers.any ;
@ -400,6 +403,55 @@ public class OidcClientRegistrationTests {
@@ -400,6 +403,55 @@ public class OidcClientRegistrationTests {
. andReturn ( ) ;
}
// gh-1344
@Test
public void requestWhenClientRegistersWithClientSecretJwtThenClientAuthenticationSuccess ( ) throws Exception {
this . spring . register ( AuthorizationServerConfiguration . class ) . autowire ( ) ;
// @formatter:off
OidcClientRegistration clientRegistration = OidcClientRegistration . builder ( )
. clientName ( "client-name" )
. redirectUri ( "https://client.example.com" )
. grantType ( AuthorizationGrantType . AUTHORIZATION_CODE . getValue ( ) )
. grantType ( AuthorizationGrantType . CLIENT_CREDENTIALS . getValue ( ) )
. tokenEndpointAuthenticationMethod ( ClientAuthenticationMethod . CLIENT_SECRET_JWT . getValue ( ) )
. scope ( "scope1" )
. scope ( "scope2" )
. build ( ) ;
// @formatter:on
OidcClientRegistration clientRegistrationResponse = registerClient ( clientRegistration ) ;
JwsHeader jwsHeader = JwsHeader . with ( MacAlgorithm . HS256 )
. build ( ) ;
Instant issuedAt = Instant . now ( ) ;
Instant expiresAt = issuedAt . plus ( 1 , ChronoUnit . HOURS ) ;
JwtClaimsSet jwtClaimsSet = JwtClaimsSet . builder ( )
. issuer ( clientRegistrationResponse . getClientId ( ) )
. subject ( clientRegistrationResponse . getClientId ( ) )
. audience ( Collections . singletonList ( asUrl ( this . authorizationServerSettings . getIssuer ( ) , this . authorizationServerSettings . getTokenEndpoint ( ) ) ) )
. issuedAt ( issuedAt )
. expiresAt ( expiresAt )
. build ( ) ;
JWKSet jwkSet = new JWKSet ( TestJwks . jwk (
new SecretKeySpec ( clientRegistrationResponse . getClientSecret ( ) . getBytes ( ) , "HS256" ) ) . build ( ) ) ;
JwtEncoder jwtClientAssertionEncoder = new NimbusJwtEncoder ( ( jwkSelector , securityContext ) - > jwkSelector . select ( jwkSet ) ) ;
Jwt jwtAssertion = jwtClientAssertionEncoder . encode ( JwtEncoderParameters . from ( jwsHeader , jwtClaimsSet ) ) ;
this . mvc . perform ( post ( DEFAULT_TOKEN_ENDPOINT_URI )
. param ( OAuth2ParameterNames . GRANT_TYPE , AuthorizationGrantType . CLIENT_CREDENTIALS . getValue ( ) )
. param ( OAuth2ParameterNames . SCOPE , "scope1" )
. param ( OAuth2ParameterNames . CLIENT_ASSERTION_TYPE , "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" )
. param ( OAuth2ParameterNames . CLIENT_ASSERTION , jwtAssertion . getTokenValue ( ) )
. param ( OAuth2ParameterNames . CLIENT_ID , clientRegistrationResponse . getClientId ( ) ) )
. andExpect ( status ( ) . isOk ( ) )
. andExpect ( jsonPath ( "$.access_token" ) . isNotEmpty ( ) )
. andExpect ( jsonPath ( "$.scope" ) . value ( "scope1" ) ) ;
}
private OidcClientRegistration registerClient ( OidcClientRegistration clientRegistration ) throws Exception {
// ***** (1) Obtain the "initial" access token used for registering the client