Ver Fonte

Fix expected @Transient Authentication at provider configuration endpoint

Closes gh-632
Joe Grandja há 3 anos atrás
pai
commit
ccf4a2de6e

+ 33 - 9
oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java

@@ -16,7 +16,9 @@
 package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
 
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.servlet.AsyncContext;
@@ -270,16 +272,9 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
 		}
 
 		SecurityContextRepository securityContextRepositoryTransientNotSaved = new SecurityContextRepository() {
-			// OAuth2ClientAuthenticationToken is @Transient and is accepted by
-			// OAuth2TokenEndpointFilter, OAuth2TokenIntrospectionEndpointFilter and OAuth2TokenRevocationEndpointFilter
-			private final RequestMatcher clientAuthenticationRequestMatcher = new OrRequestMatcher(
-					getRequestMatcher(OAuth2TokenEndpointConfigurer.class),
-					getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class),
-					OAuth2AuthorizationServerConfigurer.this.tokenIntrospectionEndpointMatcher);
 
-			// JwtAuthenticationToken is @Transient and is accepted by
-			// OidcUserInfoEndpointFilter and OidcClientRegistrationEndpointFilter
-			private final RequestMatcher jwtAuthenticationRequestMatcher = getRequestMatcher(OidcConfigurer.class);
+			private final RequestMatcher clientAuthenticationRequestMatcher = initClientAuthenticationRequestMatcher();
+			private final RequestMatcher jwtAuthenticationRequestMatcher = initJwtAuthenticationRequestMatcher();
 
 			@Override
 			public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
@@ -348,6 +343,35 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
 				return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null;
 			}
 
+			private RequestMatcher initClientAuthenticationRequestMatcher() {
+				// OAuth2ClientAuthenticationToken is @Transient and is accepted by
+				// OAuth2TokenEndpointFilter, OAuth2TokenIntrospectionEndpointFilter and OAuth2TokenRevocationEndpointFilter
+
+				List<RequestMatcher> requestMatchers = new ArrayList<>();
+				requestMatchers.add(getRequestMatcher(OAuth2TokenEndpointConfigurer.class));
+				requestMatchers.add(getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class));
+				requestMatchers.add(OAuth2AuthorizationServerConfigurer.this.tokenIntrospectionEndpointMatcher);
+				return new OrRequestMatcher(requestMatchers);
+			}
+
+			private RequestMatcher initJwtAuthenticationRequestMatcher() {
+				// JwtAuthenticationToken is @Transient and is accepted by
+				// OidcUserInfoEndpointFilter and OidcClientRegistrationEndpointFilter
+
+				List<RequestMatcher> requestMatchers = new ArrayList<>();
+				requestMatchers.add(
+						getConfigurer(OidcConfigurer.class)
+								.getConfigurer(OidcUserInfoEndpointConfigurer.class).getRequestMatcher()
+				);
+				OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer =
+						getConfigurer(OidcConfigurer.class)
+								.getConfigurer(OidcClientRegistrationEndpointConfigurer.class);
+				if (clientRegistrationEndpointConfigurer != null) {
+					requestMatchers.add(clientRegistrationEndpointConfigurer.getRequestMatcher());
+				}
+				return new OrRequestMatcher(requestMatchers);
+			}
+
 		};
 
 		builder.setSharedObject(SecurityContextRepository.class, securityContextRepositoryTransientNotSaved);

+ 38 - 16
oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcConfigurer.java

@@ -16,7 +16,9 @@
 package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
 
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.springframework.http.HttpMethod;
 import org.springframework.security.config.Customizer;
@@ -40,8 +42,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
  * @see OidcProviderConfigurationEndpointFilter
  */
 public final class OidcConfigurer extends AbstractOAuth2Configurer {
-	private final OidcUserInfoEndpointConfigurer userInfoEndpointConfigurer;
-	private OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer;
+	private final Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> configurers = new LinkedHashMap<>();
 	private RequestMatcher requestMatcher;
 
 	/**
@@ -49,7 +50,7 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
 	 */
 	OidcConfigurer(ObjectPostProcessor<Object> objectPostProcessor) {
 		super(objectPostProcessor);
-		this.userInfoEndpointConfigurer = new OidcUserInfoEndpointConfigurer(objectPostProcessor);
+		addConfigurer(OidcUserInfoEndpointConfigurer.class, new OidcUserInfoEndpointConfigurer(objectPostProcessor));
 	}
 
 	/**
@@ -59,10 +60,14 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
 	 * @return the {@link OidcConfigurer} for further configuration
 	 */
 	public OidcConfigurer clientRegistrationEndpoint(Customizer<OidcClientRegistrationEndpointConfigurer> clientRegistrationEndpointCustomizer) {
-		if (this.clientRegistrationEndpointConfigurer == null) {
-			this.clientRegistrationEndpointConfigurer = new OidcClientRegistrationEndpointConfigurer(getObjectPostProcessor());
+		OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer =
+				getConfigurer(OidcClientRegistrationEndpointConfigurer.class);
+		if (clientRegistrationEndpointConfigurer == null) {
+			addConfigurer(OidcClientRegistrationEndpointConfigurer.class,
+					new OidcClientRegistrationEndpointConfigurer(getObjectPostProcessor()));
+			clientRegistrationEndpointConfigurer = getConfigurer(OidcClientRegistrationEndpointConfigurer.class);
 		}
-		clientRegistrationEndpointCustomizer.customize(this.clientRegistrationEndpointConfigurer);
+		clientRegistrationEndpointCustomizer.customize(clientRegistrationEndpointConfigurer);
 		return this;
 	}
 
@@ -73,32 +78,40 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
 	 * @return the {@link OidcConfigurer} for further configuration
 	 */
 	public OidcConfigurer userInfoEndpoint(Customizer<OidcUserInfoEndpointConfigurer> userInfoEndpointCustomizer) {
-		userInfoEndpointCustomizer.customize(this.userInfoEndpointConfigurer);
+		userInfoEndpointCustomizer.customize(getConfigurer(OidcUserInfoEndpointConfigurer.class));
 		return this;
 	}
 
 	@Override
 	<B extends HttpSecurityBuilder<B>> void init(B builder) {
-		this.userInfoEndpointConfigurer.init(builder);
-		if (this.clientRegistrationEndpointConfigurer != null) {
-			this.clientRegistrationEndpointConfigurer.init(builder);
+		OidcUserInfoEndpointConfigurer userInfoEndpointConfigurer =
+				getConfigurer(OidcUserInfoEndpointConfigurer.class);
+		userInfoEndpointConfigurer.init(builder);
+		OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer =
+				getConfigurer(OidcClientRegistrationEndpointConfigurer.class);
+		if (clientRegistrationEndpointConfigurer != null) {
+			clientRegistrationEndpointConfigurer.init(builder);
 		}
 
 		List<RequestMatcher> requestMatchers = new ArrayList<>();
 		requestMatchers.add(new AntPathRequestMatcher(
 				"/.well-known/openid-configuration", HttpMethod.GET.name()));
-		requestMatchers.add(this.userInfoEndpointConfigurer.getRequestMatcher());
-		if (this.clientRegistrationEndpointConfigurer != null) {
-			requestMatchers.add(this.clientRegistrationEndpointConfigurer.getRequestMatcher());
+		requestMatchers.add(userInfoEndpointConfigurer.getRequestMatcher());
+		if (clientRegistrationEndpointConfigurer != null) {
+			requestMatchers.add(clientRegistrationEndpointConfigurer.getRequestMatcher());
 		}
 		this.requestMatcher = new OrRequestMatcher(requestMatchers);
 	}
 
 	@Override
 	<B extends HttpSecurityBuilder<B>> void configure(B builder) {
-		this.userInfoEndpointConfigurer.configure(builder);
-		if (this.clientRegistrationEndpointConfigurer != null) {
-			this.clientRegistrationEndpointConfigurer.configure(builder);
+		OidcUserInfoEndpointConfigurer userInfoEndpointConfigurer =
+				getConfigurer(OidcUserInfoEndpointConfigurer.class);
+		userInfoEndpointConfigurer.configure(builder);
+		OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer =
+				getConfigurer(OidcClientRegistrationEndpointConfigurer.class);
+		if (clientRegistrationEndpointConfigurer != null) {
+			clientRegistrationEndpointConfigurer.configure(builder);
 		}
 
 		ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
@@ -112,4 +125,13 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
 		return this.requestMatcher;
 	}
 
+	@SuppressWarnings("unchecked")
+	<T> T getConfigurer(Class<T> type) {
+		return (T) this.configurers.get(type);
+	}
+
+	private <T extends AbstractOAuth2Configurer> void addConfigurer(Class<T> configurerType, T configurer) {
+		this.configurers.put(configurerType, configurer);
+	}
+
 }

+ 10 - 0
oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java

@@ -186,6 +186,16 @@ public class OidcTests {
 				.andExpect(jsonPath("issuer").value(ISSUER_URL));
 	}
 
+	// gh-632
+	@Test
+	public void requestWhenConfigurationRequestAndUserAuthenticatedThenReturnConfigurationResponse() throws Exception {
+		this.spring.register(AuthorizationServerConfiguration.class).autowire();
+
+		this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)
+				.with(user("user")))
+				.andExpect(status().is2xxSuccessful());
+	}
+
 	@Test
 	public void loadContextWhenIssuerNotValidUrlThenThrowException() {
 		assertThatThrownBy(