commit
						21783faede
					
				| 
						 | 
					@ -31,6 +31,7 @@ import org.springframework.context.annotation.Conditional;
 | 
				
			||||||
import org.springframework.context.annotation.Configuration;
 | 
					import org.springframework.context.annotation.Configuration;
 | 
				
			||||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
 | 
					import org.springframework.security.config.web.server.ServerHttpSecurity;
 | 
				
			||||||
import org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec;
 | 
					import org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.JwtValidators;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders;
 | 
					import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders;
 | 
				
			||||||
| 
						 | 
					@ -43,6 +44,7 @@ import org.springframework.security.web.server.SecurityWebFilterChain;
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Madhura Bhave
 | 
					 * @author Madhura Bhave
 | 
				
			||||||
 * @author Artsiom Yudovin
 | 
					 * @author Artsiom Yudovin
 | 
				
			||||||
 | 
					 * @author HaiTao Zhang
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Configuration(proxyBeanMethods = false)
 | 
					@Configuration(proxyBeanMethods = false)
 | 
				
			||||||
class ReactiveOAuth2ResourceServerJwkConfiguration {
 | 
					class ReactiveOAuth2ResourceServerJwkConfiguration {
 | 
				
			||||||
| 
						 | 
					@ -60,7 +62,13 @@ class ReactiveOAuth2ResourceServerJwkConfiguration {
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
		@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
 | 
							@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
 | 
				
			||||||
		ReactiveJwtDecoder jwtDecoder() {
 | 
							ReactiveJwtDecoder jwtDecoder() {
 | 
				
			||||||
			return new NimbusReactiveJwtDecoder(this.properties.getJwkSetUri());
 | 
								NimbusReactiveJwtDecoder nimbusReactiveJwtDecoder = new NimbusReactiveJwtDecoder(
 | 
				
			||||||
 | 
										this.properties.getJwkSetUri());
 | 
				
			||||||
 | 
								String issuerUri = this.properties.getIssuerUri();
 | 
				
			||||||
 | 
								if (issuerUri != null) {
 | 
				
			||||||
 | 
									nimbusReactiveJwtDecoder.setJwtValidator(JwtValidators.createDefaultWithIssuer(issuerUri));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nimbusReactiveJwtDecoder;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ import org.springframework.security.config.annotation.web.configurers.oauth2.ser
 | 
				
			||||||
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 | 
					import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.JwtDecoder;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.JwtDecoders;
 | 
					import org.springframework.security.oauth2.jwt.JwtDecoders;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.JwtValidators;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -44,8 +45,10 @@ import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Madhura Bhave
 | 
					 * @author Madhura Bhave
 | 
				
			||||||
 * @author Artsiom Yudovin
 | 
					 * @author Artsiom Yudovin
 | 
				
			||||||
 | 
					 * @author HaiTao Zhang
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Configuration(proxyBeanMethods = false)
 | 
					@Configuration(proxyBeanMethods = false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OAuth2ResourceServerJwtConfiguration {
 | 
					class OAuth2ResourceServerJwtConfiguration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Configuration(proxyBeanMethods = false)
 | 
						@Configuration(proxyBeanMethods = false)
 | 
				
			||||||
| 
						 | 
					@ -61,8 +64,13 @@ class OAuth2ResourceServerJwtConfiguration {
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
		@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
 | 
							@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
 | 
				
			||||||
		JwtDecoder jwtDecoderByJwkKeySetUri() {
 | 
							JwtDecoder jwtDecoderByJwkKeySetUri() {
 | 
				
			||||||
			return NimbusJwtDecoder.withJwkSetUri(this.properties.getJwkSetUri())
 | 
								NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder.withJwkSetUri(this.properties.getJwkSetUri())
 | 
				
			||||||
					.jwsAlgorithm(SignatureAlgorithm.from(this.properties.getJwsAlgorithm())).build();
 | 
										.jwsAlgorithm(SignatureAlgorithm.from(this.properties.getJwsAlgorithm())).build();
 | 
				
			||||||
 | 
								String issuerUri = this.properties.getIssuerUri();
 | 
				
			||||||
 | 
								if (issuerUri != null) {
 | 
				
			||||||
 | 
									nimbusJwtDecoder.setJwtValidator(JwtValidators.createDefaultWithIssuer(issuerUri));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nimbusJwtDecoder;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive;
 | 
					package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
| 
						 | 
					@ -42,6 +43,10 @@ import org.springframework.security.config.BeanIds;
 | 
				
			||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
 | 
					import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
 | 
				
			||||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
 | 
					import org.springframework.security.config.web.server.ServerHttpSecurity;
 | 
				
			||||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
 | 
					import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.Jwt;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
 | 
				
			||||||
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 | 
					import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 | 
				
			||||||
| 
						 | 
					@ -318,6 +323,30 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests {
 | 
				
			||||||
						"Only one of jwt.public-key-location and opaquetoken.introspection-uri should be configured."));
 | 
											"Only one of jwt.public-key-location and opaquetoken.introspection-uri should be configured."));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@SuppressWarnings("unchecked")
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						void autoConfigurationShouldConfigureResourceServerUsingJwkSetUriAndIssuerUri() throws Exception {
 | 
				
			||||||
 | 
							this.server = new MockWebServer();
 | 
				
			||||||
 | 
							this.server.start();
 | 
				
			||||||
 | 
							String path = "test";
 | 
				
			||||||
 | 
							String issuer = this.server.url(path).toString();
 | 
				
			||||||
 | 
							String cleanIssuerPath = cleanIssuerPath(issuer);
 | 
				
			||||||
 | 
							setupMockResponse(cleanIssuerPath);
 | 
				
			||||||
 | 
							this.contextRunner
 | 
				
			||||||
 | 
									.withPropertyValues("spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com",
 | 
				
			||||||
 | 
											"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://" + this.server.getHostName() + ":"
 | 
				
			||||||
 | 
													+ this.server.getPort() + "/" + path)
 | 
				
			||||||
 | 
									.run((context) -> {
 | 
				
			||||||
 | 
										assertThat(context).hasSingleBean(ReactiveJwtDecoder.class);
 | 
				
			||||||
 | 
										ReactiveJwtDecoder reactiveJwtDecoder = context.getBean(ReactiveJwtDecoder.class);
 | 
				
			||||||
 | 
										DelegatingOAuth2TokenValidator<Jwt> jwtValidator = (DelegatingOAuth2TokenValidator) ReflectionTestUtils
 | 
				
			||||||
 | 
												.getField(reactiveJwtDecoder, "jwtValidator");
 | 
				
			||||||
 | 
										Collection<OAuth2TokenValidator<Jwt>> tokenValidators = (Collection<OAuth2TokenValidator<Jwt>>) ReflectionTestUtils
 | 
				
			||||||
 | 
												.getField(jwtValidator, "tokenValidators");
 | 
				
			||||||
 | 
										assertThat(tokenValidators.stream()).hasAtLeastOneElementOfType(JwtIssuerValidator.class);
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void assertFilterConfiguredWithJwtAuthenticationManager(AssertableReactiveWebApplicationContext context) {
 | 
						private void assertFilterConfiguredWithJwtAuthenticationManager(AssertableReactiveWebApplicationContext context) {
 | 
				
			||||||
		MatcherSecurityWebFilterChain filterChain = (MatcherSecurityWebFilterChain) context
 | 
							MatcherSecurityWebFilterChain filterChain = (MatcherSecurityWebFilterChain) context
 | 
				
			||||||
				.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
 | 
									.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet;
 | 
					package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
| 
						 | 
					@ -41,7 +42,11 @@ import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.http.MediaType;
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
import org.springframework.security.config.BeanIds;
 | 
					import org.springframework.security.config.BeanIds;
 | 
				
			||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 | 
					import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.Jwt;
 | 
				
			||||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
 | 
					import org.springframework.security.oauth2.jwt.JwtDecoder;
 | 
				
			||||||
 | 
					import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
 | 
				
			||||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
 | 
					import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
 | 
				
			||||||
import org.springframework.security.oauth2.server.resource.authentication.OAuth2IntrospectionAuthenticationToken;
 | 
					import org.springframework.security.oauth2.server.resource.authentication.OAuth2IntrospectionAuthenticationToken;
 | 
				
			||||||
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
 | 
					import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
 | 
				
			||||||
| 
						 | 
					@ -320,6 +325,30 @@ class OAuth2ResourceServerAutoConfigurationTests {
 | 
				
			||||||
						"Only one of jwt.public-key-location and opaquetoken.introspection-uri should be configured."));
 | 
											"Only one of jwt.public-key-location and opaquetoken.introspection-uri should be configured."));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@SuppressWarnings("unchecked")
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						void autoConfigurationShouldConfigureResourceServerUsingJwkSetUriAndIssuerUri() throws Exception {
 | 
				
			||||||
 | 
							this.server = new MockWebServer();
 | 
				
			||||||
 | 
							this.server.start();
 | 
				
			||||||
 | 
							String path = "test";
 | 
				
			||||||
 | 
							String issuer = this.server.url(path).toString();
 | 
				
			||||||
 | 
							String cleanIssuerPath = cleanIssuerPath(issuer);
 | 
				
			||||||
 | 
							setupMockResponse(cleanIssuerPath);
 | 
				
			||||||
 | 
							this.contextRunner
 | 
				
			||||||
 | 
									.withPropertyValues("spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com",
 | 
				
			||||||
 | 
											"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://" + this.server.getHostName() + ":"
 | 
				
			||||||
 | 
													+ this.server.getPort() + "/" + path)
 | 
				
			||||||
 | 
									.run((context) -> {
 | 
				
			||||||
 | 
										assertThat(context).hasSingleBean(JwtDecoder.class);
 | 
				
			||||||
 | 
										JwtDecoder jwtDecoder = context.getBean(JwtDecoder.class);
 | 
				
			||||||
 | 
										DelegatingOAuth2TokenValidator<Jwt> jwtValidator = (DelegatingOAuth2TokenValidator) ReflectionTestUtils
 | 
				
			||||||
 | 
												.getField(jwtDecoder, "jwtValidator");
 | 
				
			||||||
 | 
										Collection<OAuth2TokenValidator<Jwt>> tokenValidators = (Collection<OAuth2TokenValidator<Jwt>>) ReflectionTestUtils
 | 
				
			||||||
 | 
												.getField(jwtValidator, "tokenValidators");
 | 
				
			||||||
 | 
										assertThat(tokenValidators.stream()).hasAtLeastOneElementOfType(JwtIssuerValidator.class);
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Filter getBearerTokenFilter(AssertableWebApplicationContext context) {
 | 
						private Filter getBearerTokenFilter(AssertableWebApplicationContext context) {
 | 
				
			||||||
		FilterChainProxy filterChain = (FilterChainProxy) context.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
 | 
							FilterChainProxy filterChain = (FilterChainProxy) context.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
 | 
				
			||||||
		List<SecurityFilterChain> filterChains = filterChain.getFilterChains();
 | 
							List<SecurityFilterChain> filterChains = filterChain.getFilterChains();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue