I'm doing migration from Spring Boot 3.2.8 to 3.4.0 and Spring Cloud 2023.0.3 to 2024.0.0. My application uses OAuth2 with Spring Security in quite a normal way:
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@EnableFeignClients
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(JwtDecoder decoder, HttpSecurity http) throws Exception {
http.authorizeHttpRequests(httpRequests -> httpRequests
.requestMatchers("/actuator/**", "/v3/api-docs/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(AbstractHttpConfigurer::disable)
.oauth2ResourceServer(jwtConf -> jwtConf.jwt(jwtConfigurer -> jwtConfigurer.decoder(decoder)));
return http.build();
}
}
Here's my application.yml
:
spring:
security:
oauth2:
resourceserver:
jwt:
jws-algorithms: ${JWS_ALGORITHMS}
issuer-uri: ${ISSUER_URI}
jwk-set-uri: ${JWK_SET_URI}
With Spring Boot 3.2.8 everything works fine, but after I switch the version to 3.4.0 incoming requests start failing with
org.springframework.security.oauth2.server.resource.InvalidBearerTokenException: An error occurred while attempting to decode the Jwt: Unable to obtain X509Certificate from current request.
at org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.getJwt(JwtAuthenticationProvider.java:103) ~[spring-security-oauth2-resource-server-6.4.1.jar:6.4.1]
at org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.authenticate(JwtAuthenticationProvider.java:88) ~[spring-security-oauth2-resource-server-6.4.1.jar:6.4.1]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-6.4.1.jar:6.4.1]
at org.springframework.security.authentication.ObservationAuthenticationManager.lambda$authenticate$1(ObservationAuthenticationManager.java:54) ~[spring-security-core-6.4.1.jar:6.4.1]
at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.14.1.jar:1.14.1]
at org.springframework.security.authentication.ObservationAuthenticationManager.authenticate(ObservationAuthenticationManager.java:53) ~[spring-security-core-6.4.1.jar:6.4.1]
at org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:137) ~[spring-security-oauth2-resource-server-6.4.1.jar:6.4.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.0.jar:6.2.0]
Here is how my jwks.json
looks like:
"keys" : [ {
"kty" : "RSA",
"use" : "sig",
"alg" : "PS256",
"kid" : "kid",
"x5c" : [ "lost-of-chars==" ],
"x5t#S256" : "lost-of-chars",
"e" : "AQAB",
"n" : "lost-of-chars"
}
I've looked into migration guide but haven't found any clue. My question is how could I fix this.
P.S. The same happens with Spring Boot 3.3.0
Currently I work this around with this declaration
@Bean
JwtDecoder jwtDecoderByJwkKeySetUri(
ObjectProvider<JwkSetUriJwtDecoderBuilderCustomizer> customizers,
OAuth2ResourceServerProperties properties
) {
var jwt = properties.getJwt();
var builder = NimbusJwtDecoder
.withJwkSetUri(jwt.getJwkSetUri())
.jwsAlgorithms(signatureAlgorithms ->
jwt.getJwsAlgorithms().stream().map(SignatureAlgorithm::from).forEach(signatureAlgorithms::add)
);
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
var issuerUri = jwt.getIssuerUri();
var validators = List.of(new JwtIssuerValidator(issuerUri), new JwtTimestampValidator());
var defaultValidator = new DelegatingOAuth2TokenValidator<>(validators);
var nimbusJwtDecoder = builder.build();
nimbusJwtDecoder.setJwtValidator(defaultValidator);
return nimbusJwtDecoder;
}
However, I suspect to do migration in a proper way I need to supply certificate somehow.