diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthProviderConfigurator.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthProviderConfigurator.java index 9950b7ca666..4ab07c84c14 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthProviderConfigurator.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthProviderConfigurator.java @@ -82,8 +82,7 @@ public String getIdpAuthenticationUrl( var responseType = URLEncoder.encode(definition.getResponseType(), StandardCharsets.UTF_8); var relyingPartyId = definition.getRelyingPartyId(); - var state = generateStateParam(); - SessionUtils.setStateParam(request.getSession(), SessionUtils.stateParameterAttributeKeyForIdp(idpOriginKey), state); + var state = SessionUtils.setStateParam(request.getSession(), SessionUtils.stateParameterAttributeKeyForIdp(idpOriginKey), generateStateParam()); UriComponentsBuilder uriBuilder = UriComponentsBuilder .fromUriString(idpUrlBase) @@ -96,9 +95,8 @@ public String getIdpAuthenticationUrl( // https://docs.spring.io/spring-security/site/docs/5.3.1.RELEASE/reference/html5/#initiating-the-authorization-request if (isPkceNeeded(definition)) { var pkceVerifier = new S256PkceVerifier(); - var codeVerifier = generateCodeVerifier(); - var codeChallenge = pkceVerifier.compute(codeVerifier); - SessionUtils.setStateParam(request.getSession(), SessionUtils.codeVerifierParameterAttributeKeyForIdp(idpOriginKey), codeVerifier); + var codeVerifier = SessionUtils.setStateParam(request.getSession(), SessionUtils.codeVerifierParameterAttributeKeyForIdp(idpOriginKey), generateCodeVerifier()); + var codeChallenge = SessionUtils.setStateParam(request.getSession(), SessionUtils.codeChallengeParameterAttributeKeyForIdp(idpOriginKey), pkceVerifier.compute(codeVerifier)); uriBuilder.queryParam("code_challenge", codeChallenge); uriBuilder.queryParam("code_challenge_method", pkceVerifier.getCodeChallengeMethod()); } diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/util/SessionUtils.java b/server/src/main/java/org/cloudfoundry/identity/uaa/util/SessionUtils.java index 9d733ce4485..41a590ebc67 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/util/SessionUtils.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/util/SessionUtils.java @@ -26,6 +26,7 @@ public final class SessionUtils { private static final String EXTERNAL_OAUTH_STATE_ATTRIBUTE_PREFIX = "external-oauth-state-"; private static final String EXTERNAL_OAUTH_CODE_VERIFIER_ATTRIBUTE_PREFIX = "external-oauth-verifier-"; + private static final String EXTERNAL_OAUTH_CODE_CHALLENGE_ATTRIBUTE_PREFIX = "external-oauth-challenge-"; private SessionUtils() { } @@ -56,8 +57,13 @@ public static UaaAuthentication getForcePasswordExpiredUser(HttpSession session) return (UaaAuthentication) session.getAttribute(FORCE_PASSWORD_EXPIRED_USER); } - public static void setStateParam(HttpSession session, String stateParamKey, String state) { - session.setAttribute(stateParamKey, state); + public static String setStateParam(HttpSession session, String stateParamKey, String state) { + if (session.isNew() || session.getAttribute(stateParamKey) == null) { + session.setAttribute(stateParamKey, state); + return state; + } else { + return session.getAttribute(stateParamKey) instanceof String existingState ? existingState : null; + } } public static Object getStateParam(HttpSession session, String stateParamKey) { @@ -87,4 +93,8 @@ public static String stateParameterAttributeKeyForIdp(String idpOriginKey) { public static String codeVerifierParameterAttributeKeyForIdp(String idpOriginKey) { return EXTERNAL_OAUTH_CODE_VERIFIER_ATTRIBUTE_PREFIX + idpOriginKey; } + + public static String codeChallengeParameterAttributeKeyForIdp(String idpOriginKey) { + return EXTERNAL_OAUTH_CODE_CHALLENGE_ATTRIBUTE_PREFIX + idpOriginKey; + } }