@ -1071,6 +1071,94 @@ public class OAuth2AuthorizationCodeGrantTests {
@@ -1071,6 +1071,94 @@ public class OAuth2AuthorizationCodeGrantTests {
. isEqualTo ( true ) ;
}
// gh-2182
@Test
public void requestWhenPushedAuthorizationRequestAndRequiresConsentThenDisplaysConsentPage ( ) throws Exception {
this . spring . register ( AuthorizationServerConfigurationWithPushedAuthorizationRequests . class ) . autowire ( ) ;
RegisteredClient registeredClient = TestRegisteredClients . registeredClient ( ) . scopes ( ( scopes ) - > {
scopes . clear ( ) ;
scopes . add ( "message.read" ) ;
scopes . add ( "message.write" ) ;
} ) . clientSettings ( ClientSettings . builder ( ) . requireAuthorizationConsent ( true ) . build ( ) ) . build ( ) ;
this . registeredClientRepository . save ( registeredClient ) ;
MvcResult mvcResult = this . mvc
. perform ( post ( "/oauth2/par" ) . params ( getAuthorizationRequestParameters ( registeredClient ) )
. header ( HttpHeaders . AUTHORIZATION , getAuthorizationHeader ( registeredClient ) ) )
. andExpect ( header ( ) . string ( HttpHeaders . CACHE_CONTROL , containsString ( "no-store" ) ) )
. andExpect ( header ( ) . string ( HttpHeaders . PRAGMA , containsString ( "no-cache" ) ) )
. andExpect ( status ( ) . isCreated ( ) )
. andExpect ( jsonPath ( "$.request_uri" ) . isNotEmpty ( ) )
. andExpect ( jsonPath ( "$.expires_in" ) . isNotEmpty ( ) )
. andReturn ( ) ;
String requestUri = JsonPath . read ( mvcResult . getResponse ( ) . getContentAsString ( ) , "$.request_uri" ) ;
String consentPage = this . mvc
. perform ( get ( DEFAULT_AUTHORIZATION_ENDPOINT_URI )
. queryParam ( OAuth2ParameterNames . CLIENT_ID , registeredClient . getClientId ( ) )
. queryParam ( OAuth2ParameterNames . REQUEST_URI , requestUri )
. with ( user ( "user" ) ) )
. andExpect ( status ( ) . is2xxSuccessful ( ) )
. andReturn ( )
. getResponse ( )
. getContentAsString ( ) ;
assertThat ( consentPage ) . contains ( "Consent required" ) ;
assertThat ( consentPage ) . contains ( scopeCheckbox ( "message.read" ) ) ;
assertThat ( consentPage ) . contains ( scopeCheckbox ( "message.write" ) ) ;
}
// gh-2182
@Test
public void requestWhenPushedAuthorizationRequestAndCustomConsentPageConfiguredThenRedirect ( ) throws Exception {
this . spring . register ( AuthorizationServerConfigurationWithPushedAuthorizationRequestsAndCustomConsentPage . class )
. autowire ( ) ;
RegisteredClient registeredClient = TestRegisteredClients . registeredClient ( ) . scopes ( ( scopes ) - > {
scopes . clear ( ) ;
scopes . add ( "message.read" ) ;
scopes . add ( "message.write" ) ;
} ) . clientSettings ( ClientSettings . builder ( ) . requireAuthorizationConsent ( true ) . build ( ) ) . build ( ) ;
this . registeredClientRepository . save ( registeredClient ) ;
MvcResult mvcResult = this . mvc
. perform ( post ( "/oauth2/par" ) . params ( getAuthorizationRequestParameters ( registeredClient ) )
. header ( HttpHeaders . AUTHORIZATION , getAuthorizationHeader ( registeredClient ) ) )
. andExpect ( header ( ) . string ( HttpHeaders . CACHE_CONTROL , containsString ( "no-store" ) ) )
. andExpect ( header ( ) . string ( HttpHeaders . PRAGMA , containsString ( "no-cache" ) ) )
. andExpect ( status ( ) . isCreated ( ) )
. andExpect ( jsonPath ( "$.request_uri" ) . isNotEmpty ( ) )
. andExpect ( jsonPath ( "$.expires_in" ) . isNotEmpty ( ) )
. andReturn ( ) ;
String requestUri = JsonPath . read ( mvcResult . getResponse ( ) . getContentAsString ( ) , "$.request_uri" ) ;
mvcResult = this . mvc
. perform ( get ( DEFAULT_AUTHORIZATION_ENDPOINT_URI )
. queryParam ( OAuth2ParameterNames . CLIENT_ID , registeredClient . getClientId ( ) )
. queryParam ( OAuth2ParameterNames . REQUEST_URI , requestUri )
. with ( user ( "user" ) ) )
. andExpect ( status ( ) . is3xxRedirection ( ) )
. andReturn ( ) ;
String redirectedUrl = mvcResult . getResponse ( ) . getRedirectedUrl ( ) ;
assertThat ( redirectedUrl ) . matches ( "http://localhost/oauth2/consent\\?scope=.+&client_id=.+&state=.+" ) ;
String locationHeader = URLDecoder . decode ( redirectedUrl , StandardCharsets . UTF_8 . name ( ) ) ;
UriComponents uriComponents = UriComponentsBuilder . fromUriString ( locationHeader ) . build ( ) ;
MultiValueMap < String , String > redirectQueryParams = uriComponents . getQueryParams ( ) ;
assertThat ( uriComponents . getPath ( ) ) . isEqualTo ( consentPage ) ;
assertThat ( redirectQueryParams . getFirst ( OAuth2ParameterNames . SCOPE ) ) . isEqualTo ( "message.read message.write" ) ;
assertThat ( redirectQueryParams . getFirst ( OAuth2ParameterNames . CLIENT_ID ) )
. isEqualTo ( registeredClient . getClientId ( ) ) ;
String state = extractParameterFromRedirectUri ( redirectedUrl , "state" ) ;
OAuth2Authorization authorization = this . authorizationService . findByToken ( state , STATE_TOKEN_TYPE ) ;
assertThat ( authorization ) . isNotNull ( ) ;
}
private static OAuth2Authorization createAuthorization ( RegisteredClient registeredClient ) {
Map < String , Object > additionalParameters = new HashMap < > ( ) ;
additionalParameters . put ( PkceParameterNames . CODE_CHALLENGE , S256_CODE_CHALLENGE ) ;
@ -1125,8 +1213,8 @@ public class OAuth2AuthorizationCodeGrantTests {
@@ -1125,8 +1213,8 @@ public class OAuth2AuthorizationCodeGrantTests {
private static String getAuthorizationHeader ( RegisteredClient registeredClient ) throws Exception {
String clientId = registeredClient . getClientId ( ) ;
String clientSecret = registeredClient . getClientSecret ( ) ;
clientId = URLEncoder . encode ( clientId , StandardCharsets . UTF_8 . name ( ) ) ;
clientSecret = URLEncoder . encode ( clientSecret , StandardCharsets . UTF_8 . name ( ) ) ;
clientId = URLEncoder . encode ( clientId , StandardCharsets . UTF_8 ) ;
clientSecret = URLEncoder . encode ( clientSecret , StandardCharsets . UTF_8 ) ;
String credentialsString = clientId + ":" + clientSecret ;
byte [ ] encodedBytes = Base64 . getEncoder ( ) . encode ( credentialsString . getBytes ( StandardCharsets . UTF_8 ) ) ;
return "Basic " + new String ( encodedBytes , StandardCharsets . UTF_8 ) ;
@ -1496,4 +1584,28 @@ public class OAuth2AuthorizationCodeGrantTests {
@@ -1496,4 +1584,28 @@ public class OAuth2AuthorizationCodeGrantTests {
}
@EnableWebSecurity
@Configuration ( proxyBeanMethods = false )
static class AuthorizationServerConfigurationWithPushedAuthorizationRequestsAndCustomConsentPage
extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
SecurityFilterChain authorizationServerSecurityFilterChain ( HttpSecurity http ) throws Exception {
http
. oauth2AuthorizationServer ( ( authorizationServer ) - >
authorizationServer
. pushedAuthorizationRequestEndpoint ( Customizer . withDefaults ( ) )
. authorizationEndpoint ( ( authorizationEndpoint ) - >
authorizationEndpoint . consentPage ( consentPage ) )
)
. authorizeHttpRequests ( ( authorize ) - >
authorize . anyRequest ( ) . authenticated ( )
) ;
return http . build ( ) ;
}
// @formatter:on
}
}