VYPR
Medium severity6.1NVD Advisory· Published Mar 20, 2024· Updated Apr 15, 2026

CVE-2024-22258

CVE-2024-22258

Description

Spring Authorization Server versions 1.0.0 - 1.0.5, 1.1.0 - 1.1.5, 1.2.0 - 1.2.2 and older unsupported versions are susceptible to a PKCE Downgrade Attack for Confidential Clients.

Specifically, an application is vulnerable when a Confidential Client uses PKCE for the Authorization Code Grant.

An application is not vulnerable when a Public Client uses PKCE for the Authorization Code Grant.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.springframework.security:spring-security-oauth2-authorization-serverMaven
< 1.1.61.1.6
org.springframework.security:spring-security-oauth2-authorization-serverMaven
>= 1.2.0, < 1.2.31.2.3

Patches

1
a7035d22bd2d

Update PKCE validation

2 files changed · +34 4
  • oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/CodeVerifierAuthenticator.java+4 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2020-2022 the original author or authors.
    + * Copyright 2020-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -94,8 +94,10 @@ private boolean authenticate(OAuth2ClientAuthenticationToken clientAuthenticatio
     
     		String codeChallenge = (String) authorizationRequest.getAdditionalParameters()
     				.get(PkceParameterNames.CODE_CHALLENGE);
    +		String codeVerifier = (String) parameters.get(PkceParameterNames.CODE_VERIFIER);
     		if (!StringUtils.hasText(codeChallenge)) {
    -			if (registeredClient.getClientSettings().isRequireProofKey()) {
    +			if (registeredClient.getClientSettings().isRequireProofKey() ||
    +					StringUtils.hasText(codeVerifier)) {
     				throwInvalidGrant(PkceParameterNames.CODE_CHALLENGE);
     			} else {
     				if (this.logger.isTraceEnabled()) {
    @@ -111,7 +113,6 @@ private boolean authenticate(OAuth2ClientAuthenticationToken clientAuthenticatio
     
     		String codeChallengeMethod = (String) authorizationRequest.getAdditionalParameters()
     				.get(PkceParameterNames.CODE_CHALLENGE_METHOD);
    -		String codeVerifier = (String) parameters.get(PkceParameterNames.CODE_VERIFIER);
     		if (!codeVerifierValid(codeVerifier, codeChallenge, codeChallengeMethod)) {
     			throwInvalidGrant(PkceParameterNames.CODE_VERIFIER);
     		}
    
  • oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java+30 1 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2020-2023 the original author or authors.
    + * Copyright 2020-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -488,6 +488,35 @@ public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeThenErro
     		assertThat(redirectedUrl).isEqualTo(expectedRedirectUri);
     	}
     
    +	@Test
    +	public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeButCodeVerifierProvidedThenBadRequest() throws Exception {
    +		this.spring.register(AuthorizationServerConfiguration.class).autowire();
    +
    +		RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
    +		this.registeredClientRepository.save(registeredClient);
    +
    +		MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient);
    +		MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI)
    +						.queryParams(authorizationRequestParameters)
    +						.with(user("user")))
    +				.andExpect(status().is3xxRedirection())
    +				.andReturn();
    +		String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
    +		String expectedRedirectUri = authorizationRequestParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI);
    +		assertThat(redirectedUrl).matches(expectedRedirectUri + "\\?code=.{15,}&state=" + STATE_URL_ENCODED);
    +
    +		String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code");
    +		OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE);
    +		assertThat(authorizationCodeAuthorization).isNotNull();
    +		assertThat(authorizationCodeAuthorization.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
    +
    +		this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
    +				.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
    +				.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER)
    +				.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
    +				.andExpect(status().isBadRequest());
    +	}
    +
     	@Test
     	public void requestWhenCustomTokenGeneratorThenUsed() throws Exception {
     		this.spring.register(AuthorizationServerConfigurationWithTokenGenerator.class).autowire();
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.