diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfiguration.java index 78f28f94b81..92c02ca9d43 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 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. @@ -40,7 +40,9 @@ import org.springframework.security.config.annotation.web.reactive.EnableWebFlux @ConditionalOnClass({ EnableWebFluxSecurity.class }) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @Import({ ReactiveOAuth2ResourceServerConfiguration.JwtConfiguration.class, - ReactiveOAuth2ResourceServerConfiguration.OpaqueTokenConfiguration.class }) + ReactiveOAuth2ResourceServerConfiguration.OpaqueTokenConfiguration.class, + ReactiveOAuth2ResourceServerConfiguration.JwtWebSecurityConfiguration.class, + ReactiveOAuth2ResourceServerConfiguration.OpaqueTokenWebSecurityConfiguration.class }) public class ReactiveOAuth2ResourceServerAutoConfiguration { } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerConfiguration.java index d4f5388f041..6cedf7e711c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 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. @@ -24,8 +24,8 @@ import org.springframework.security.oauth2.server.resource.authentication.Bearer import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; /** - * Configuration classes for OAuth2 Resource Server These should be {@code @Import} in a - * regular auto-configuration class to guarantee their order of execution. + * Configuration classes for OAuth2 Resource Server. These should be {@code @Import}ed in + * a regular auto-configuration class to guarantee their order of execution. * * @author Madhura Bhave */ @@ -33,18 +33,30 @@ class ReactiveOAuth2ResourceServerConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ BearerTokenAuthenticationToken.class, ReactiveJwtDecoder.class }) - @Import({ ReactiveOAuth2ResourceServerJwkConfiguration.JwtConfiguration.class, - ReactiveOAuth2ResourceServerJwkConfiguration.WebSecurityConfiguration.class }) + @Import(ReactiveOAuth2ResourceServerJwkConfiguration.JwtConfiguration.class) static class JwtConfiguration { } + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({ BearerTokenAuthenticationToken.class, ReactiveJwtDecoder.class }) + @Import(ReactiveOAuth2ResourceServerJwkConfiguration.WebSecurityConfiguration.class) + static class JwtWebSecurityConfiguration { + + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ BearerTokenAuthenticationToken.class, ReactiveOpaqueTokenIntrospector.class }) - @Import({ ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.OpaqueTokenIntrospectionClientConfiguration.class, - ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.WebSecurityConfiguration.class }) + @Import(ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.OpaqueTokenIntrospectionClientConfiguration.class) static class OpaqueTokenConfiguration { } + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({ BearerTokenAuthenticationToken.class, ReactiveOpaqueTokenIntrospector.class }) + @Import(ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.WebSecurityConfiguration.class) + static class OpaqueTokenWebSecurityConfiguration { + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java index 31cb13aa60c..0c10d879b97 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java @@ -164,11 +164,11 @@ class ReactiveOAuth2ResourceServerJwkConfiguration { } @Configuration(proxyBeanMethods = false) + @ConditionalOnBean(ReactiveJwtDecoder.class) @ConditionalOnMissingBean(SecurityWebFilterChain.class) static class WebSecurityConfiguration { @Bean - @ConditionalOnBean(ReactiveJwtDecoder.class) SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ReactiveJwtDecoder jwtDecoder) { http.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated()); http.oauth2ResourceServer((server) -> customDecoder(server, jwtDecoder)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java index dbeb778d876..6612dfe703c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java @@ -56,10 +56,10 @@ class ReactiveOAuth2ResourceServerOpaqueTokenConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(SecurityWebFilterChain.class) + @ConditionalOnBean(ReactiveOpaqueTokenIntrospector.class) static class WebSecurityConfiguration { @Bean - @ConditionalOnBean(ReactiveOpaqueTokenIntrospector.class) SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.authorizeExchange((exchanges) -> exchanges.anyExchange().authenticated()); http.oauth2ResourceServer((resourceServer) -> resourceServer.opaqueToken(withDefaults())); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java index 9583efcbc45..d60b395c1bb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java @@ -43,6 +43,8 @@ import org.mockito.InOrder; import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener; +import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -73,6 +75,7 @@ import org.springframework.security.oauth2.server.resource.authentication.Opaque import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; import org.springframework.security.web.server.MatcherSecurityWebFilterChain; import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.security.web.server.authentication.AuthenticationWebFilter; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.server.WebFilter; @@ -116,10 +119,16 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { } } + @Test + void autoConfigurationDoesNotEnableWebSecurityWithoutJwtDecoderOrTokenIntrospector() { + this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(WebFilterChainProxy.class)); + } + @Test void autoConfigurationShouldConfigureResourceServer() { this.contextRunner .withPropertyValues("spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com") + .withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO)) .run((context) -> { assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class); assertFilterConfiguredWithJwtAuthenticationManager(context); @@ -385,7 +394,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { @Test void autoConfigurationWhenIntrospectionUriAvailableShouldConfigureIntrospectionClient() { - this.contextRunner + this.contextRunner.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO)) .withPropertyValues( "spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://check-token.com", "spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id",