From ccf4a2de6e210cb2d3250dd38f5accdf8885284f Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 22 Mar 2022 13:45:57 -0400 Subject: [PATCH] Fix expected @Transient Authentication at provider configuration endpoint Closes gh-632 --- .../OAuth2AuthorizationServerConfigurer.java | 42 +++++++++++---- .../server/authorization/OidcConfigurer.java | 54 +++++++++++++------ .../server/authorization/OidcTests.java | 10 ++++ 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java index 4346d94a..77c78f61 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java +++ b/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 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 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); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcConfigurer.java index 560a27b1..6071a928 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcConfigurer.java +++ b/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, AbstractOAuth2Configurer> configurers = new LinkedHashMap<>(); private RequestMatcher requestMatcher; /** @@ -49,7 +50,7 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer { */ OidcConfigurer(ObjectPostProcessor 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 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 userInfoEndpointCustomizer) { - userInfoEndpointCustomizer.customize(this.userInfoEndpointConfigurer); + userInfoEndpointCustomizer.customize(getConfigurer(OidcUserInfoEndpointConfigurer.class)); return this; } @Override > 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 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 > 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 getConfigurer(Class type) { + return (T) this.configurers.get(type); + } + + private void addConfigurer(Class configurerType, T configurer) { + this.configurers.put(configurerType, configurer); + } + } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java index 178ac7b1..1d5b207d 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java +++ b/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(