Skip to content

Commit 39eb574

Browse files
committed
handle issuers with issuer path correctly
1 parent a7b256d commit 39eb574

File tree

4 files changed

+68
-22
lines changed

4 files changed

+68
-22
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java

+37-2
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@
1515
*/
1616
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
1717

18+
import java.net.URI;
19+
import java.net.URISyntaxException;
1820
import java.util.function.Consumer;
1921

2022
import org.springframework.http.HttpMethod;
2123
import org.springframework.security.config.annotation.ObjectPostProcessor;
2224
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
2325
import org.springframework.security.oauth2.server.authorization.oidc.OidcProviderConfiguration;
2426
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter;
27+
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
2528
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
2629
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
2730
import org.springframework.security.web.util.matcher.RequestMatcher;
31+
import org.springframework.util.StringUtils;
2832

2933
/**
3034
* Configurer for the OpenID Connect 1.0 Provider Configuration Endpoint.
@@ -35,6 +39,10 @@
3539
* @see OidcProviderConfigurationEndpointFilter
3640
*/
3741
public final class OidcProviderConfigurationEndpointConfigurer extends AbstractOAuth2Configurer {
42+
/**
43+
* The default endpoint {@code URI} for OpenID Provider Configuration requests.
44+
*/
45+
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
3846
private RequestMatcher requestMatcher;
3947
private Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer;
4048
private Consumer<OidcProviderConfiguration.Builder> defaultProviderConfigurationCustomizer;
@@ -70,13 +78,13 @@ void addDefaultProviderConfigurationCustomizer(
7078
@Override
7179
void init(HttpSecurity httpSecurity) {
7280
this.requestMatcher = new AntPathRequestMatcher(
73-
"/.well-known/openid-configuration", HttpMethod.GET.name());
81+
getConfigurationEndpointUri(httpSecurity), HttpMethod.GET.name());
7482
}
7583

7684
@Override
7785
void configure(HttpSecurity httpSecurity) {
7886
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
79-
new OidcProviderConfigurationEndpointFilter();
87+
new OidcProviderConfigurationEndpointFilter(getConfigurationEndpointUri(httpSecurity));
8088
Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer = getProviderConfigurationCustomizer();
8189
if (providerConfigurationCustomizer != null) {
8290
oidcProviderConfigurationEndpointFilter.setProviderConfigurationCustomizer(providerConfigurationCustomizer);
@@ -105,4 +113,31 @@ RequestMatcher getRequestMatcher() {
105113
return this.requestMatcher;
106114
}
107115

116+
private String getConfigurationEndpointUri(HttpSecurity httpSecurity) {
117+
return getIssuerPath(httpSecurity) + DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
118+
}
119+
120+
private String getIssuerPath(HttpSecurity httpSecurity) {
121+
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils
122+
.getAuthorizationServerSettings(httpSecurity);
123+
String issuer = authorizationServerSettings.getIssuer();
124+
if (StringUtils.hasText(issuer)) {
125+
try {
126+
URI issuerUri = new URI(issuer);
127+
String path = issuerUri.getPath();
128+
if (path == null) {
129+
path = "";
130+
} else if (path.endsWith("/")) {
131+
path = path.substring(0, path.length() - 1);
132+
}
133+
134+
return path;
135+
} catch (URISyntaxException e) {
136+
throw new RuntimeException("Error building configuration path", e);
137+
}
138+
} else {
139+
return "";
140+
}
141+
}
142+
108143
}

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java

+5-8
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,15 @@
5454
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest">4.1. OpenID Provider Configuration Request</a>
5555
*/
5656
public final class OidcProviderConfigurationEndpointFilter extends OncePerRequestFilter {
57-
/**
58-
* The default endpoint {@code URI} for OpenID Provider Configuration requests.
59-
*/
60-
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
61-
62-
private final RequestMatcher requestMatcher = new AntPathRequestMatcher(
63-
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI,
64-
HttpMethod.GET.name());
57+
private final RequestMatcher requestMatcher;
6558
private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter =
6659
new OidcProviderConfigurationHttpMessageConverter();
6760
private Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer = (providerConfiguration) -> {};
6861

62+
public OidcProviderConfigurationEndpointFilter(String configurationEndpointUri) {
63+
requestMatcher = new AntPathRequestMatcher(configurationEndpointUri, HttpMethod.GET.name());
64+
}
65+
6966
/**
7067
* Sets the {@code Consumer} providing access to the {@link OidcProviderConfiguration.Builder}
7168
* allowing the ability to customize the claims of the OpenID Provider's configuration.

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
*/
6363
@ExtendWith(SpringTestContextExtension.class)
6464
public class OidcProviderConfigurationTests {
65-
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
65+
private static final String ISSUER1_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/issuer1/.well-known/openid-configuration";
6666
private static final String ISSUER_URL = "https://example.com/issuer1";
6767

6868
public final SpringTestContext spring = new SpringTestContext();
@@ -77,7 +77,7 @@ public class OidcProviderConfigurationTests {
7777
public void requestWhenConfigurationRequestAndIssuerSetThenReturnDefaultConfigurationResponse() throws Exception {
7878
this.spring.register(AuthorizationServerConfiguration.class).autowire();
7979

80-
this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
80+
this.mvc.perform(get(ISSUER1_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
8181
.andExpect(status().is2xxSuccessful())
8282
.andExpectAll(defaultConfigurationMatchers());
8383
}
@@ -87,7 +87,7 @@ public void requestWhenConfigurationRequestAndIssuerSetThenReturnDefaultConfigur
8787
public void requestWhenConfigurationRequestAndUserAuthenticatedThenReturnConfigurationResponse() throws Exception {
8888
this.spring.register(AuthorizationServerConfiguration.class).autowire();
8989

90-
this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)
90+
this.mvc.perform(get(ISSUER1_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)
9191
.with(user("user")))
9292
.andExpect(status().is2xxSuccessful())
9393
.andExpectAll(defaultConfigurationMatchers());
@@ -98,7 +98,7 @@ public void requestWhenConfigurationRequestAndUserAuthenticatedThenReturnConfigu
9898
public void requestWhenConfigurationRequestAndConfigurationCustomizerSetThenReturnCustomConfigurationResponse() throws Exception {
9999
this.spring.register(AuthorizationServerConfigurationWithProviderConfigurationCustomizer.class).autowire();
100100

101-
this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
101+
this.mvc.perform(get(ISSUER1_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
102102
.andExpect(status().is2xxSuccessful())
103103
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
104104
hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL)));
@@ -108,7 +108,7 @@ public void requestWhenConfigurationRequestAndConfigurationCustomizerSetThenRetu
108108
public void requestWhenConfigurationRequestAndClientRegistrationEnabledThenConfigurationResponseIncludesRegistrationEndpoint() throws Exception {
109109
this.spring.register(AuthorizationServerConfigurationWithClientRegistrationEnabled.class).autowire();
110110

111-
this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
111+
this.mvc.perform(get(ISSUER1_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
112112
.andExpect(status().is2xxSuccessful())
113113
.andExpectAll(defaultConfigurationMatchers())
114114
.andExpect(jsonPath("$.registration_endpoint").value(ISSUER_URL.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint())));

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java

+21-7
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
*/
4646
public class OidcProviderConfigurationEndpointFilterTests {
4747
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
48-
private final OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
4948

5049
@AfterEach
5150
public void cleanup() {
@@ -54,39 +53,51 @@ public void cleanup() {
5453

5554
@Test
5655
public void setProviderConfigurationCustomizerWhenNullThenThrowIllegalArgumentException() {
57-
assertThatThrownBy(() -> this.filter.setProviderConfigurationCustomizer(null))
56+
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(
57+
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
58+
59+
assertThatThrownBy(() -> filter.setProviderConfigurationCustomizer(null))
5860
.isInstanceOf(IllegalArgumentException.class)
5961
.hasMessage("providerConfigurationCustomizer cannot be null");
6062
}
6163

6264
@Test
6365
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
66+
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(
67+
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
68+
6469
String requestUri = "/path";
6570
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
6671
request.setServletPath(requestUri);
6772
MockHttpServletResponse response = new MockHttpServletResponse();
6873
FilterChain filterChain = mock(FilterChain.class);
6974

70-
this.filter.doFilter(request, response, filterChain);
75+
filter.doFilter(request, response, filterChain);
7176

7277
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
7378
}
7479

7580
@Test
7681
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
82+
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(
83+
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
84+
7785
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
7886
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
7987
request.setServletPath(requestUri);
8088
MockHttpServletResponse response = new MockHttpServletResponse();
8189
FilterChain filterChain = mock(FilterChain.class);
8290

83-
this.filter.doFilter(request, response, filterChain);
91+
filter.doFilter(request, response, filterChain);
8492

8593
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
8694
}
8795

8896
@Test
8997
public void doFilterWhenConfigurationRequestThenConfigurationResponse() throws Exception {
98+
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(
99+
"/issuer1" + DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
100+
90101
String issuer = "https://example.com/issuer1";
91102
String authorizationEndpoint = "/oauth2/v1/authorize";
92103
String tokenEndpoint = "/oauth2/v1/token";
@@ -108,13 +119,13 @@ public void doFilterWhenConfigurationRequestThenConfigurationResponse() throws E
108119
.build();
109120
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
110121

111-
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
122+
String requestUri = "/issuer1" + DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
112123
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
113124
request.setServletPath(requestUri);
114125
MockHttpServletResponse response = new MockHttpServletResponse();
115126
FilterChain filterChain = mock(FilterChain.class);
116127

117-
this.filter.doFilter(request, response, filterChain);
128+
filter.doFilter(request, response, filterChain);
118129

119130
verifyNoInteractions(filterChain);
120131

@@ -140,6 +151,9 @@ public void doFilterWhenConfigurationRequestThenConfigurationResponse() throws E
140151

141152
@Test
142153
public void doFilterWhenAuthorizationServerSettingsWithInvalidIssuerThenThrowIllegalArgumentException() {
154+
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(
155+
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
156+
143157
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
144158
.issuer("https://this is an invalid URL")
145159
.build();
@@ -152,7 +166,7 @@ public void doFilterWhenAuthorizationServerSettingsWithInvalidIssuerThenThrowIll
152166
FilterChain filterChain = mock(FilterChain.class);
153167

154168
assertThatIllegalArgumentException()
155-
.isThrownBy(() -> this.filter.doFilter(request, response, filterChain))
169+
.isThrownBy(() -> filter.doFilter(request, response, filterChain))
156170
.withMessage("issuer must be a valid URL");
157171
}
158172

0 commit comments

Comments
 (0)