Browse Source

Enable PKCE by default in authorization server

Closes gh-18020
pull/18025/head
Joe Grandja 2 months ago
parent
commit
1cca9c5822
  1. 70
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java
  2. 2
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenIntrospectionTests.java
  3. 21
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java
  4. 4
      oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java
  5. 31
      oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProviderTests.java
  6. 58
      oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java
  7. 31
      oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2PushedAuthorizationRequestAuthenticationProviderTests.java
  8. 2
      oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java

70
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java

@ -26,6 +26,7 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -359,7 +360,7 @@ public class OAuth2AuthorizationCodeGrantTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
OAuth2AccessTokenResponse accessTokenResponse = assertTokenRequestReturnsAccessTokenResponse(registeredClient, OAuth2AccessTokenResponse accessTokenResponse = assertTokenRequestReturnsAccessTokenResponse(registeredClient,
@ -384,7 +385,7 @@ public class OAuth2AuthorizationCodeGrantTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
assertTokenRequestReturnsAccessTokenResponse(registeredClient, authorization, assertTokenRequestReturnsAccessTokenResponse(registeredClient, authorization,
@ -433,8 +434,6 @@ public class OAuth2AuthorizationCodeGrantTests {
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.queryParams(getAuthorizationRequestParameters(registeredClient)) .queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user"))) .with(user("user")))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andReturn(); .andReturn();
@ -451,8 +450,7 @@ public class OAuth2AuthorizationCodeGrantTests {
this.mvc this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -487,8 +485,6 @@ public class OAuth2AuthorizationCodeGrantTests {
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.queryParams(getAuthorizationRequestParameters(registeredClient)) .queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user"))) .with(user("user")))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andReturn(); .andReturn();
@ -505,8 +501,7 @@ public class OAuth2AuthorizationCodeGrantTests {
this.mvc this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -542,11 +537,11 @@ public class OAuth2AuthorizationCodeGrantTests {
tokenRequestParameters.set(OAuth2ParameterNames.CODE, ""); tokenRequestParameters.set(OAuth2ParameterNames.CODE, "");
tokenRequestParameters.set(OAuth2ParameterNames.REDIRECT_URI, tokenRequestParameters.set(OAuth2ParameterNames.REDIRECT_URI,
registeredClient.getRedirectUris().iterator().next()); registeredClient.getRedirectUris().iterator().next());
tokenRequestParameters.set(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER);
this.mvc this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(tokenRequestParameters) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(tokenRequestParameters)
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
} }
@ -561,8 +556,6 @@ public class OAuth2AuthorizationCodeGrantTests {
registeredClient); registeredClient);
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user"))) .with(user("user")))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andReturn(); .andReturn();
@ -577,9 +570,12 @@ public class OAuth2AuthorizationCodeGrantTests {
assertThat(authorizationCodeAuthorization.getAuthorizationGrantType()) assertThat(authorizationCodeAuthorization.getAuthorizationGrantType())
.isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
MultiValueMap<String, String> tokenRequestParameters = getTokenRequestParameters(registeredClient,
authorizationCodeAuthorization);
tokenRequestParameters.remove(PkceParameterNames.CODE_VERIFIER);
this.mvc this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(tokenRequestParameters)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
@ -595,11 +591,12 @@ public class OAuth2AuthorizationCodeGrantTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().redirectUris((redirectUris) -> { RegisteredClient registeredClient = TestRegisteredClients.registeredClient().redirectUris((redirectUris) -> {
redirectUris.clear(); redirectUris.clear();
redirectUris.add(redirectUri); redirectUris.add(redirectUri);
}).clientSettings(ClientSettings.builder().requireProofKey(true).build()).build(); }).build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters( MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(
registeredClient); registeredClient);
authorizationRequestParameters.remove(PkceParameterNames.CODE_CHALLENGE);
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
.with(user("user"))) .with(user("user")))
@ -618,11 +615,14 @@ public class OAuth2AuthorizationCodeGrantTests {
throws Exception { throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.spring.register(AuthorizationServerConfiguration.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(ClientSettings.builder().requireProofKey(false).build())
.build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters( MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(
registeredClient); registeredClient);
authorizationRequestParameters.remove(PkceParameterNames.CODE_CHALLENGE);
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
.with(user("user"))) .with(user("user")))
@ -642,7 +642,6 @@ public class OAuth2AuthorizationCodeGrantTests {
this.mvc this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER)
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
} }
@ -654,7 +653,7 @@ public class OAuth2AuthorizationCodeGrantTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
this.mvc this.mvc
@ -704,10 +703,14 @@ public class OAuth2AuthorizationCodeGrantTests {
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient) OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient)
.principalName("user") .principalName("user")
.build(); .build();
Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
OAuth2AuthorizationRequest authorizationRequest = authorization OAuth2AuthorizationRequest authorizationRequest = authorization
.getAttribute(OAuth2AuthorizationRequest.class.getName()); .getAttribute(OAuth2AuthorizationRequest.class.getName());
OAuth2AuthorizationRequest updatedAuthorizationRequest = OAuth2AuthorizationRequest.from(authorizationRequest) OAuth2AuthorizationRequest updatedAuthorizationRequest = OAuth2AuthorizationRequest.from(authorizationRequest)
.state(STATE_URL_UNENCODED) .state(STATE_URL_UNENCODED)
.additionalParameters(additionalParameters)
.build(); .build();
authorization = OAuth2Authorization.from(authorization) authorization = OAuth2Authorization.from(authorization)
.attribute(OAuth2AuthorizationRequest.class.getName(), updatedAuthorizationRequest) .attribute(OAuth2AuthorizationRequest.class.getName(), updatedAuthorizationRequest)
@ -793,7 +796,7 @@ public class OAuth2AuthorizationCodeGrantTests {
.build(); .build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
OAuth2AuthorizationRequest authorizationRequest = authorization OAuth2AuthorizationRequest authorizationRequest = authorization
.getAttribute(OAuth2AuthorizationRequest.class.getName()); .getAttribute(OAuth2AuthorizationRequest.class.getName());
OAuth2AuthorizationRequest updatedAuthorizationRequest = OAuth2AuthorizationRequest.from(authorizationRequest) OAuth2AuthorizationRequest updatedAuthorizationRequest = OAuth2AuthorizationRequest.from(authorizationRequest)
@ -906,8 +909,6 @@ public class OAuth2AuthorizationCodeGrantTests {
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
.queryParams(getAuthorizationRequestParameters(registeredClient)) .queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user"))) .with(user("user")))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andReturn(); .andReturn();
@ -926,8 +927,7 @@ public class OAuth2AuthorizationCodeGrantTests {
mvcResult = this.mvc mvcResult = this.mvc
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -956,8 +956,6 @@ public class OAuth2AuthorizationCodeGrantTests {
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)) .perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI))
.queryParams(getAuthorizationRequestParameters(registeredClient)) .queryParams(getAuthorizationRequestParameters(registeredClient))
.queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.with(user("user"))) .with(user("user")))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andReturn(); .andReturn();
@ -969,8 +967,7 @@ public class OAuth2AuthorizationCodeGrantTests {
this.mvc this.mvc
.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) .perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI))
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()))
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -994,7 +991,7 @@ public class OAuth2AuthorizationCodeGrantTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
String tokenEndpointUri = "http://localhost" + DEFAULT_TOKEN_ENDPOINT_URI; String tokenEndpointUri = "http://localhost" + DEFAULT_TOKEN_ENDPOINT_URI;
@ -1025,8 +1022,6 @@ public class OAuth2AuthorizationCodeGrantTests {
MvcResult mvcResult = this.mvc MvcResult mvcResult = this.mvc
.perform(post("/oauth2/par").params(getAuthorizationRequestParameters(registeredClient)) .perform(post("/oauth2/par").params(getAuthorizationRequestParameters(registeredClient))
.param(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE)
.param(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
@ -1053,7 +1048,6 @@ public class OAuth2AuthorizationCodeGrantTests {
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) .perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER)
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store")))
.andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache")))
@ -1077,6 +1071,13 @@ public class OAuth2AuthorizationCodeGrantTests {
.isEqualTo(true); .isEqualTo(true);
} }
private static OAuth2Authorization createAuthorization(RegisteredClient registeredClient) {
Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
return TestOAuth2Authorizations.authorization(registeredClient, additionalParameters).build();
}
private static String generateDPoPProof(String tokenEndpointUri) { private static String generateDPoPProof(String tokenEndpointUri) {
// @formatter:off // @formatter:off
Map<String, Object> publicJwk = TestJwks.DEFAULT_EC_JWK Map<String, Object> publicJwk = TestJwks.DEFAULT_EC_JWK
@ -1105,6 +1106,8 @@ public class OAuth2AuthorizationCodeGrantTests {
parameters.set(OAuth2ParameterNames.SCOPE, parameters.set(OAuth2ParameterNames.SCOPE,
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " ")); StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
parameters.set(OAuth2ParameterNames.STATE, STATE_URL_UNENCODED); parameters.set(OAuth2ParameterNames.STATE, STATE_URL_UNENCODED);
parameters.set(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
parameters.set(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
return parameters; return parameters;
} }
@ -1115,6 +1118,7 @@ public class OAuth2AuthorizationCodeGrantTests {
parameters.set(OAuth2ParameterNames.CODE, parameters.set(OAuth2ParameterNames.CODE,
authorization.getToken(OAuth2AuthorizationCode.class).getToken().getTokenValue()); authorization.getToken(OAuth2AuthorizationCode.class).getToken().getTokenValue());
parameters.set(OAuth2ParameterNames.REDIRECT_URI, registeredClient.getRedirectUris().iterator().next()); parameters.set(OAuth2ParameterNames.REDIRECT_URI, registeredClient.getRedirectUris().iterator().next());
parameters.set(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER);
return parameters; return parameters;
} }

2
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenIntrospectionTests.java

@ -89,6 +89,7 @@ import org.springframework.security.oauth2.server.authorization.client.TestRegis
import org.springframework.security.oauth2.server.authorization.http.converter.OAuth2TokenIntrospectionHttpMessageConverter; import org.springframework.security.oauth2.server.authorization.http.converter.OAuth2TokenIntrospectionHttpMessageConverter;
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin; import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat; import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings; import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext; import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
@ -310,6 +311,7 @@ public class OAuth2TokenIntrospectionTests {
.build(); .build();
RegisteredClient authorizedRegisteredClient = TestRegisteredClients.registeredClient() RegisteredClient authorizedRegisteredClient = TestRegisteredClients.registeredClient()
.tokenSettings(tokenSettings) .tokenSettings(tokenSettings)
.clientSettings(ClientSettings.builder().requireProofKey(false).build())
.build(); .build();
// @formatter:on // @formatter:on
this.registeredClientRepository.save(authorizedRegisteredClient); this.registeredClientRepository.save(authorizedRegisteredClient);

21
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java

@ -22,8 +22,10 @@ import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.Principal; import java.security.Principal;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.JWKSet;
@ -69,6 +71,7 @@ import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.endpoint.PkceParameterNames;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import org.springframework.security.oauth2.core.oidc.OidcScopes; import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
@ -133,6 +136,12 @@ public class OidcTests {
private static final String DEFAULT_OIDC_LOGOUT_ENDPOINT_URI = "/connect/logout"; private static final String DEFAULT_OIDC_LOGOUT_ENDPOINT_URI = "/connect/logout";
// See RFC 7636: Appendix B. Example for the S256 code_challenge_method
// https://tools.ietf.org/html/rfc7636#appendix-B
private static final String S256_CODE_VERIFIER = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
private static final String S256_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM";
private static final String AUTHORITIES_CLAIM = "authorities"; private static final String AUTHORITIES_CLAIM = "authorities";
private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE); private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE);
@ -462,7 +471,7 @@ public class OidcTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); OAuth2Authorization authorization = createAuthorization(registeredClient);
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
this.mvc this.mvc
@ -557,6 +566,13 @@ public class OidcTests {
.andReturn(); .andReturn();
} }
private static OAuth2Authorization createAuthorization(RegisteredClient registeredClient) {
Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
return TestOAuth2Authorizations.authorization(registeredClient, additionalParameters).build();
}
private static MultiValueMap<String, String> getAuthorizationRequestParameters(RegisteredClient registeredClient) { private static MultiValueMap<String, String> getAuthorizationRequestParameters(RegisteredClient registeredClient) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(); MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.set(OAuth2ParameterNames.RESPONSE_TYPE, OAuth2AuthorizationResponseType.CODE.getValue()); parameters.set(OAuth2ParameterNames.RESPONSE_TYPE, OAuth2AuthorizationResponseType.CODE.getValue());
@ -565,6 +581,8 @@ public class OidcTests {
parameters.set(OAuth2ParameterNames.SCOPE, parameters.set(OAuth2ParameterNames.SCOPE,
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " ")); StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
parameters.set(OAuth2ParameterNames.STATE, "state"); parameters.set(OAuth2ParameterNames.STATE, "state");
parameters.set(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
parameters.set(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
return parameters; return parameters;
} }
@ -575,6 +593,7 @@ public class OidcTests {
parameters.set(OAuth2ParameterNames.CODE, parameters.set(OAuth2ParameterNames.CODE,
authorization.getToken(OAuth2AuthorizationCode.class).getToken().getTokenValue()); authorization.getToken(OAuth2AuthorizationCode.class).getToken().getTokenValue());
parameters.set(OAuth2ParameterNames.REDIRECT_URI, registeredClient.getRedirectUris().iterator().next()); parameters.set(OAuth2ParameterNames.REDIRECT_URI, registeredClient.getRedirectUris().iterator().next());
parameters.set(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER);
return parameters; return parameters;
} }

4
oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java

@ -44,7 +44,7 @@ public final class ClientSettings extends AbstractSettings {
/** /**
* Returns {@code true} if the client is required to provide a proof key challenge and * Returns {@code true} if the client is required to provide a proof key challenge and
* verifier when performing the Authorization Code Grant flow. The default is * verifier when performing the Authorization Code Grant flow. The default is
* {@code false}. * {@code true}.
* @return {@code true} if the client is required to provide a proof key challenge and * @return {@code true} if the client is required to provide a proof key challenge and
* verifier, {@code false} otherwise * verifier, {@code false} otherwise
*/ */
@ -99,7 +99,7 @@ public final class ClientSettings extends AbstractSettings {
* @return the {@link Builder} * @return the {@link Builder}
*/ */
public static Builder builder() { public static Builder builder() {
return new Builder().requireProofKey(false).requireAuthorizationConsent(false); return new Builder().requireProofKey(true).requireAuthorizationConsent(false);
} }
/** /**

31
oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProviderTests.java

@ -267,11 +267,12 @@ public class ClientSecretAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2Authorization authorization = createAuthorization(registeredClient);
given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
.willReturn(TestOAuth2Authorizations.authorization().build()); .willReturn(authorization);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
registeredClient.getClientSecret(), createAuthorizationCodeTokenParameters()); registeredClient.getClientSecret(), createPkceTokenParameters(S256_CODE_VERIFIER));
OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -289,9 +290,7 @@ public class ClientSecretAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = createAuthorization(registeredClient);
.authorization(registeredClient, createPkceAuthorizationParametersS256())
.build();
given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
.willReturn(authorization); .willReturn(authorization);
@ -317,9 +316,7 @@ public class ClientSecretAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = createAuthorization(registeredClient);
.authorization(registeredClient, createPkceAuthorizationParametersS256())
.build();
given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
.willReturn(authorization); .willReturn(authorization);
@ -344,9 +341,7 @@ public class ClientSecretAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = createAuthorization(registeredClient);
.authorization(registeredClient, createPkceAuthorizationParametersS256())
.build();
given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) given(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)))
.willReturn(authorization); .willReturn(authorization);
@ -366,6 +361,13 @@ public class ClientSecretAuthenticationProviderTests {
assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient);
} }
private static OAuth2Authorization createAuthorization(RegisteredClient registeredClient) {
Map<String, Object> parameters = new HashMap<>();
parameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
parameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
return TestOAuth2Authorizations.authorization(registeredClient, parameters).build();
}
private static Map<String, Object> createAuthorizationCodeTokenParameters() { private static Map<String, Object> createAuthorizationCodeTokenParameters() {
Map<String, Object> parameters = new HashMap<>(); Map<String, Object> parameters = new HashMap<>();
parameters.put(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()); parameters.put(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue());
@ -379,11 +381,4 @@ public class ClientSecretAuthenticationProviderTests {
return parameters; return parameters;
} }
private static Map<String, Object> createPkceAuthorizationParametersS256() {
Map<String, Object> parameters = new HashMap<>();
parameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
parameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
return parameters;
}
} }

58
oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java

@ -75,6 +75,12 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorize"; private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorize";
// See RFC 7636: Appendix B. Example for the S256 code_challenge_method
// https://tools.ietf.org/html/rfc7636#appendix-B
private static final String S256_CODE_VERIFIER = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
private static final String S256_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM";
private static final String STATE = "state"; private static final String STATE = "state";
private static final OAuth2TokenType STATE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.STATE); private static final OAuth2TokenType STATE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.STATE);
@ -225,7 +231,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, "https://127.0.0.1:5000", STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, "https://127.0.0.1:5000", STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -244,7 +250,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, "https://[::1]:5000", STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, "https://[::1]:5000", STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -319,9 +325,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test @Test
public void authenticateWhenPkceRequiredAndMissingCodeChallengeThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() { public void authenticateWhenPkceRequiredAndMissingCodeChallengeThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient() RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
@ -341,7 +345,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge"); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "unsupported"); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "unsupported");
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
@ -360,7 +364,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge"); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), additionalParameters); registeredClient.getScopes(), additionalParameters);
@ -394,7 +398,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put("prompt", prompt); additionalParameters.put("prompt", prompt);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
@ -412,7 +416,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
this.principal.setAuthenticated(false); this.principal.setAuthenticated(false);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put("prompt", "none"); additionalParameters.put("prompt", "none");
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
@ -433,7 +437,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -451,7 +455,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) given(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put("prompt", "none"); additionalParameters.put("prompt", "none");
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
@ -473,7 +477,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationConsentAuthenticationToken authenticationResult = (OAuth2AuthorizationConsentAuthenticationToken) this.authenticationProvider OAuth2AuthorizationConsentAuthenticationToken authenticationResult = (OAuth2AuthorizationConsentAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -524,7 +528,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -551,7 +555,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -574,7 +578,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -592,12 +596,9 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
.willReturn(registeredClient); .willReturn(registeredClient);
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0];
Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge");
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), additionalParameters); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -614,7 +615,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri
.create(); .create();
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri()); additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri());
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = TestOAuth2Authorizations
.authorization(registeredClient, additionalParameters) .authorization(registeredClient, additionalParameters)
@ -640,7 +641,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri
.create(); .create();
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri()); additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri());
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = TestOAuth2Authorizations
.authorization(registeredClient, additionalParameters) .authorization(registeredClient, additionalParameters)
@ -665,7 +666,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri
.create(); .create();
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri()); additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri());
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = TestOAuth2Authorizations
.authorization(registeredClient, additionalParameters) .authorization(registeredClient, additionalParameters)
@ -689,7 +690,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri OAuth2PushedAuthorizationRequestUri pushedAuthorizationRequestUri = OAuth2PushedAuthorizationRequestUri
.create(Instant.now().minusSeconds(5)); .create(Instant.now().minusSeconds(5));
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri()); additionalParameters.put(OAuth2ParameterNames.REQUEST_URI, pushedAuthorizationRequestUri.getRequestUri());
OAuth2Authorization authorization = TestOAuth2Authorizations OAuth2Authorization authorization = TestOAuth2Authorizations
.authorization(registeredClient, additionalParameters) .authorization(registeredClient, additionalParameters)
@ -721,7 +722,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
assertThatExceptionOfType(OAuth2AuthorizationCodeRequestAuthenticationException.class) assertThatExceptionOfType(OAuth2AuthorizationCodeRequestAuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
@ -746,7 +747,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
@ -812,4 +813,11 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
assertThat(authorizationCodeRequestAuthentication.getRedirectUri()).isEqualTo(redirectUri); assertThat(authorizationCodeRequestAuthentication.getRedirectUri()).isEqualTo(redirectUri);
} }
private static Map<String, Object> createPkceParameters() {
Map<String, Object> parameters = new HashMap<>();
parameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
parameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
return parameters;
}
} }

31
oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2PushedAuthorizationRequestAuthenticationProviderTests.java

@ -40,7 +40,6 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients; import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -57,6 +56,12 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/par"; private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/par";
// See RFC 7636: Appendix B. Example for the S256 code_challenge_method
// https://tools.ietf.org/html/rfc7636#appendix-B
private static final String S256_CODE_VERIFIER = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
private static final String S256_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM";
private static final String STATE = "state"; private static final String STATE = "state";
private OAuth2AuthorizationService authorizationService; private OAuth2AuthorizationService authorizationService;
@ -177,7 +182,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken( OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, "https://127.0.0.1:5000", STATE, AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, "https://127.0.0.1:5000", STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult); assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult);
@ -192,7 +197,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken( OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, "https://[::1]:5000", STATE, AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, "https://[::1]:5000", STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult); assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult);
@ -246,9 +251,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
@Test @Test
public void authenticateWhenPkceRequiredAndMissingCodeChallengeThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() { public void authenticateWhenPkceRequiredAndMissingCodeChallengeThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient() RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
@ -320,7 +323,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
Map<String, Object> additionalParameters = new HashMap<>(); Map<String, Object> additionalParameters = createPkceParameters();
additionalParameters.put("prompt", prompt); additionalParameters.put("prompt", prompt);
OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken( OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE,
@ -337,12 +340,9 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[0];
Map<String, Object> additionalParameters = new HashMap<>();
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge");
additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken( OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE,
registeredClient.getScopes(), additionalParameters); registeredClient.getScopes(), createPkceParameters());
OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult); assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult);
@ -360,7 +360,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2]; String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[2];
OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken( OAuth2PushedAuthorizationRequestAuthenticationToken authentication = new OAuth2PushedAuthorizationRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE, AUTHORIZATION_URI, registeredClient.getClientId(), clientPrincipal, redirectUri, STATE,
registeredClient.getScopes(), null); registeredClient.getScopes(), createPkceParameters());
OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider OAuth2PushedAuthorizationRequestAuthenticationToken authenticationResult = (OAuth2PushedAuthorizationRequestAuthenticationToken) this.authenticationProvider
.authenticate(authentication); .authenticate(authentication);
assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult); assertPushedAuthorizationResponse(registeredClient, authentication, authenticationResult);
@ -415,4 +415,11 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
assertThat(authorizationCodeRequestAuthentication.getRedirectUri()).isEqualTo(redirectUri); assertThat(authorizationCodeRequestAuthentication.getRedirectUri()).isEqualTo(redirectUri);
} }
private static Map<String, Object> createPkceParameters() {
Map<String, Object> parameters = new HashMap<>();
parameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
parameters.put(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE);
return parameters;
}
} }

2
oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java

@ -33,7 +33,7 @@ public class ClientSettingsTests {
public void buildWhenDefaultThenDefaultsAreSet() { public void buildWhenDefaultThenDefaultsAreSet() {
ClientSettings clientSettings = ClientSettings.builder().build(); ClientSettings clientSettings = ClientSettings.builder().build();
assertThat(clientSettings.getSettings()).hasSize(2); assertThat(clientSettings.getSettings()).hasSize(2);
assertThat(clientSettings.isRequireProofKey()).isFalse(); assertThat(clientSettings.isRequireProofKey()).isTrue();
assertThat(clientSettings.isRequireAuthorizationConsent()).isFalse(); assertThat(clientSettings.isRequireAuthorizationConsent()).isFalse();
} }

Loading…
Cancel
Save