From 4587c823302fb585458c27a4ea745b41d39c477f Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 13 Oct 2025 14:09:24 -0700 Subject: [PATCH] Start building against Spring Security 7.0.0-RC1 snapshots See gh-47499 --- .../autoconfigure/endpoint/reactive/SecurityService.java | 6 +++++- .../autoconfigure/endpoint/reactive/TokenValidator.java | 7 ++++++- .../servlet/OAuth2AuthorizationServerProperties.java | 2 +- .../OAuth2ResourceServerAutoConfigurationTests.java | 6 +++++- platform/spring-boot-dependencies/build.gradle | 2 +- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/SecurityService.java b/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/SecurityService.java index 85436605a2e..079e3a2114d 100644 --- a/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/SecurityService.java +++ b/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/SecurityService.java @@ -153,7 +153,11 @@ class SecurityService { .uri(this.cloudControllerUrl + "/info") .retrieve() .bodyToMono(Map.class) - .map((response) -> (String) response.get("token_endpoint")) + .map((response) -> { + String tokenEndpoint = (String) response.get("token_endpoint"); + Assert.state(tokenEndpoint != null, "No 'token_endpoint' found in response"); + return tokenEndpoint; + }) .cache() .onErrorMap((ex) -> new CloudFoundryAuthorizationException(Reason.SERVICE_UNAVAILABLE, "Unable to fetch token keys from UAA.")); diff --git a/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/TokenValidator.java b/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/TokenValidator.java index 3d761185822..99aead7f4e8 100644 --- a/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/TokenValidator.java +++ b/module/spring-boot-cloudfoundry/src/main/java/org/springframework/boot/cloudfoundry/actuate/autoconfigure/endpoint/reactive/TokenValidator.java @@ -33,6 +33,7 @@ import reactor.core.publisher.Mono; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.CloudFoundryAuthorizationException; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.CloudFoundryAuthorizationException.Reason; import org.springframework.boot.cloudfoundry.actuate.autoconfigure.endpoint.Token; +import org.springframework.util.Assert; /** * Validator used to ensure that a signed {@link Token} has not been tampered with. @@ -85,7 +86,11 @@ class TokenValidator { return this.securityService.fetchTokenKeys() .doOnSuccess(this::cacheTokenKeys) .filter((tokenKeys) -> tokenKeys.containsKey(keyId)) - .map((tokenKeys) -> tokenKeys.get(keyId)) + .map((tokenKeys) -> { + String tokenKey = tokenKeys.get(keyId); + Assert.state(tokenKey != null, "No token key found for '%s'".formatted(keyId)); + return tokenKey; + }) .switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(Reason.INVALID_KEY_ID, "Key Id present in token header does not match"))); } diff --git a/module/spring-boot-security-oauth2-authorization-server/src/main/java/org/springframework/boot/security/oauth2/server/authorization/autoconfigure/servlet/OAuth2AuthorizationServerProperties.java b/module/spring-boot-security-oauth2-authorization-server/src/main/java/org/springframework/boot/security/oauth2/server/authorization/autoconfigure/servlet/OAuth2AuthorizationServerProperties.java index 9cc16d8bb9c..0c8b95105cf 100644 --- a/module/spring-boot-security-oauth2-authorization-server/src/main/java/org/springframework/boot/security/oauth2/server/authorization/autoconfigure/servlet/OAuth2AuthorizationServerProperties.java +++ b/module/spring-boot-security-oauth2-authorization-server/src/main/java/org/springframework/boot/security/oauth2/server/authorization/autoconfigure/servlet/OAuth2AuthorizationServerProperties.java @@ -289,7 +289,7 @@ public class OAuth2AuthorizationServerProperties implements InitializingBean { * Whether the client is required to provide a proof key challenge and verifier * when performing the Authorization Code Grant flow. */ - private boolean requireProofKey = false; + private boolean requireProofKey = true; /** * Whether authorization consent is required when the client requests access. diff --git a/module/spring-boot-security-oauth2-resource-server/src/test/java/org/springframework/boot/security/oauth2/server/resource/autoconfigure/servlet/OAuth2ResourceServerAutoConfigurationTests.java b/module/spring-boot-security-oauth2-resource-server/src/test/java/org/springframework/boot/security/oauth2/server/resource/autoconfigure/servlet/OAuth2ResourceServerAutoConfigurationTests.java index ca6518eee03..fdaf10c79d1 100644 --- a/module/spring-boot-security-oauth2-resource-server/src/test/java/org/springframework/boot/security/oauth2/server/resource/autoconfigure/servlet/OAuth2ResourceServerAutoConfigurationTests.java +++ b/module/spring-boot-security-oauth2-resource-server/src/test/java/org/springframework/boot/security/oauth2/server/resource/autoconfigure/servlet/OAuth2ResourceServerAutoConfigurationTests.java @@ -66,6 +66,7 @@ import org.springframework.security.config.BeanIds; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.FactorGrantedAuthority; import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.jwt.Jwt; @@ -674,7 +675,10 @@ class OAuth2ResourceServerAutoConfigurationTests { JwtAuthenticationConverter converter = context.getBean(JwtAuthenticationConverter.class); AbstractAuthenticationToken token = converter.convert(jwt); assertThat(token).isNotNull().extracting(AbstractAuthenticationToken::getName).isEqualTo(expectedPrincipal); - assertThat(token.getAuthorities()).extracting(GrantedAuthority::getAuthority) + assertThat(token.getAuthorities() + .stream() + .filter((authority) -> !(authority instanceof FactorGrantedAuthority))) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder(expectedAuthorities); assertThat(context).hasSingleBean(JwtDecoder.class); assertThat(getBearerTokenFilter(context)).isNotNull(); diff --git a/platform/spring-boot-dependencies/build.gradle b/platform/spring-boot-dependencies/build.gradle index a90d9e9bf81..2698758e866 100644 --- a/platform/spring-boot-dependencies/build.gradle +++ b/platform/spring-boot-dependencies/build.gradle @@ -2533,7 +2533,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-restdocs/releases/tag/v{version}") } } - library("Spring Security", "7.0.0-M3") { + library("Spring Security", "7.0.0-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { bom("spring-security-bom")