Browse Source

Path component for issuer identifier should be disabled by default

Issue gh-1342

Closes gh-1611
pull/1623/head
Joe Grandja 2 years ago
parent
commit
4cfe59cd85
  1. 30
      docs/src/main/java/sample/multitenancy/AuthorizationServerSettingsConfig.java
  2. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationEndpointConfigurer.java
  3. 15
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java
  4. 8
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataEndpointConfigurer.java
  5. 30
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientAuthenticationConfigurer.java
  6. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java
  7. 14
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceAuthorizationEndpointConfigurer.java
  8. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceVerificationEndpointConfigurer.java
  9. 15
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenEndpointConfigurer.java
  10. 15
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionEndpointConfigurer.java
  11. 14
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationEndpointConfigurer.java
  12. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationEndpointConfigurer.java
  13. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcLogoutEndpointConfigurer.java
  14. 8
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java
  15. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoEndpointConfigurer.java
  16. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java
  17. 17
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java
  18. 55
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java
  19. 6
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java
  20. 17
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java
  21. 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/JwkSetTests.java
  22. 13
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java
  23. 6
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java
  24. 14
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientCredentialsGrantTests.java
  25. 16
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceCodeGrantTests.java
  26. 25
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionTests.java
  27. 14
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationTests.java
  28. 1
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationTests.java
  29. 14
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java
  30. 2
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcTests.java
  31. 1
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoTests.java
  32. 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java
  33. 30
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java
  34. 7
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java
  35. 2
      samples/demo-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

30
docs/src/main/java/sample/multitenancy/AuthorizationServerSettingsConfig.java

@ -0,0 +1,30 @@
/*
* Copyright 2020-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.multitenancy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
@Configuration(proxyBeanMethods = false)
public class AuthorizationServerSettingsConfig {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}

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

@ -51,7 +51,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Authorization Endpoint. * Configurer for the OAuth 2.0 Authorization Endpoint.
@ -211,7 +211,9 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String authorizationEndpointUri = withMultipleIssuerPattern(authorizationServerSettings.getAuthorizationEndpoint()); String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) :
authorizationServerSettings.getAuthorizationEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.GET.name()),
new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.POST.name())); new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.POST.name()));
@ -229,11 +231,12 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
void configure(HttpSecurity httpSecurity) { void configure(HttpSecurity httpSecurity) {
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) :
authorizationServerSettings.getAuthorizationEndpoint();
OAuth2AuthorizationEndpointFilter authorizationEndpointFilter = OAuth2AuthorizationEndpointFilter authorizationEndpointFilter =
new OAuth2AuthorizationEndpointFilter( new OAuth2AuthorizationEndpointFilter(authenticationManager, authorizationEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getAuthorizationEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.authorizationRequestConverters.isEmpty()) { if (!this.authorizationRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.authorizationRequestConverters); authenticationConverters.addAll(0, this.authorizationRequestConverters);

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

@ -56,7 +56,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support. * An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support.
@ -315,8 +315,10 @@ public final class OAuth2AuthorizationServerConfigurer
configurer.init(httpSecurity); configurer.init(httpSecurity);
requestMatchers.add(configurer.getRequestMatcher()); requestMatchers.add(configurer.getRequestMatcher());
}); });
requestMatchers.add(new AntPathRequestMatcher( String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuerPattern(authorizationServerSettings.getJwkSetEndpoint()), HttpMethod.GET.name())); withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) :
authorizationServerSettings.getJwkSetEndpoint();
requestMatchers.add(new AntPathRequestMatcher(jwkSetEndpointUri, HttpMethod.GET.name()));
this.endpointsMatcher = new OrRequestMatcher(requestMatchers); this.endpointsMatcher = new OrRequestMatcher(requestMatchers);
ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling = httpSecurity.getConfigurer(ExceptionHandlingConfigurer.class); ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling = httpSecurity.getConfigurer(ExceptionHandlingConfigurer.class);
@ -343,8 +345,11 @@ public final class OAuth2AuthorizationServerConfigurer
JWKSource<com.nimbusds.jose.proc.SecurityContext> jwkSource = OAuth2ConfigurerUtils.getJwkSource(httpSecurity); JWKSource<com.nimbusds.jose.proc.SecurityContext> jwkSource = OAuth2ConfigurerUtils.getJwkSource(httpSecurity);
if (jwkSource != null) { if (jwkSource != null) {
NimbusJwkSetEndpointFilter jwkSetEndpointFilter = new NimbusJwkSetEndpointFilter( String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
jwkSource, withMultipleIssuerPattern(authorizationServerSettings.getJwkSetEndpoint())); withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) :
authorizationServerSettings.getJwkSetEndpoint();
NimbusJwkSetEndpointFilter jwkSetEndpointFilter =
new NimbusJwkSetEndpointFilter(jwkSource, jwkSetEndpointUri);
httpSecurity.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class); httpSecurity.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
} }
} }

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

@ -21,6 +21,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadata; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadata;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationServerMetadataEndpointFilter; import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationServerMetadataEndpointFilter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@ -69,8 +70,11 @@ public final class OAuth2AuthorizationServerMetadataEndpointConfigurer extends A
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
this.requestMatcher = new AntPathRequestMatcher( AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
"/.well-known/oauth-authorization-server/**", HttpMethod.GET.name()); String authorizationServerMetadataEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
"/.well-known/oauth-authorization-server/**" :
"/.well-known/oauth-authorization-server";
this.requestMatcher = new AntPathRequestMatcher(authorizationServerMetadataEndpointUri, HttpMethod.GET.name());
} }
@Override @Override

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

@ -53,7 +53,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for OAuth 2.0 Client Authentication. * Configurer for OAuth 2.0 Client Authentication.
@ -163,19 +163,23 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) :
authorizationServerSettings.getTokenEndpoint();
String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) :
authorizationServerSettings.getTokenIntrospectionEndpoint();
String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) :
authorizationServerSettings.getTokenRevocationEndpoint();
String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) :
authorizationServerSettings.getDeviceAuthorizationEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher( new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name()),
withMultipleIssuerPattern(authorizationServerSettings.getTokenEndpoint()), new AntPathRequestMatcher(tokenIntrospectionEndpointUri, HttpMethod.POST.name()),
HttpMethod.POST.name()), new AntPathRequestMatcher(tokenRevocationEndpointUri, HttpMethod.POST.name()),
new AntPathRequestMatcher( new AntPathRequestMatcher(deviceAuthorizationEndpointUri, HttpMethod.POST.name()));
withMultipleIssuerPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()),
HttpMethod.POST.name()),
new AntPathRequestMatcher(
withMultipleIssuerPattern(authorizationServerSettings.getTokenRevocationEndpoint()),
HttpMethod.POST.name()),
new AntPathRequestMatcher(
withMultipleIssuerPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()),
HttpMethod.POST.name()));
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
if (!this.authenticationProviders.isEmpty()) { if (!this.authenticationProviders.isEmpty()) {

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

@ -57,7 +57,7 @@ final class OAuth2ConfigurerUtils {
private OAuth2ConfigurerUtils() { private OAuth2ConfigurerUtils() {
} }
static String withMultipleIssuerPattern(String endpointUri) { static String withMultipleIssuersPattern(String endpointUri) {
Assert.hasText(endpointUri, "endpointUri cannot be empty"); Assert.hasText(endpointUri, "endpointUri cannot be empty");
return endpointUri.startsWith("/") ? return endpointUri.startsWith("/") ?
"/**" + endpointUri : "/**" + endpointUri :

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

@ -45,7 +45,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Device Authorization Endpoint. * Configurer for the OAuth 2.0 Device Authorization Endpoint.
@ -167,8 +167,10 @@ public final class OAuth2DeviceAuthorizationEndpointConfigurer extends AbstractO
public void init(HttpSecurity builder) { public void init(HttpSecurity builder) {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings authorizationServerSettings =
OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder);
this.requestMatcher = new AntPathRequestMatcher( String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuerPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()), HttpMethod.POST.name()); withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) :
authorizationServerSettings.getDeviceAuthorizationEndpoint();
this.requestMatcher = new AntPathRequestMatcher(deviceAuthorizationEndpointUri, HttpMethod.POST.name());
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(builder); List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(builder);
if (!this.authenticationProviders.isEmpty()) { if (!this.authenticationProviders.isEmpty()) {
@ -184,9 +186,11 @@ public final class OAuth2DeviceAuthorizationEndpointConfigurer extends AbstractO
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder);
String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) :
authorizationServerSettings.getDeviceAuthorizationEndpoint();
OAuth2DeviceAuthorizationEndpointFilter deviceAuthorizationEndpointFilter = OAuth2DeviceAuthorizationEndpointFilter deviceAuthorizationEndpointFilter =
new OAuth2DeviceAuthorizationEndpointFilter( new OAuth2DeviceAuthorizationEndpointFilter(authenticationManager, deviceAuthorizationEndpointUri);
authenticationManager, withMultipleIssuerPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.deviceAuthorizationRequestConverters.isEmpty()) { if (!this.deviceAuthorizationRequestConverters.isEmpty()) {

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

@ -50,7 +50,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Device Verification Endpoint. * Configurer for the OAuth 2.0 Device Verification Endpoint.
@ -197,7 +197,9 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA
public void init(HttpSecurity builder) { public void init(HttpSecurity builder) {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings authorizationServerSettings =
OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder);
String deviceVerificationEndpointUri = withMultipleIssuerPattern(authorizationServerSettings.getDeviceVerificationEndpoint()); String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) :
authorizationServerSettings.getDeviceVerificationEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.GET.name()),
new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.POST.name())); new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.POST.name()));
@ -217,10 +219,11 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings authorizationServerSettings =
OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder);
String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) :
authorizationServerSettings.getDeviceVerificationEndpoint();
OAuth2DeviceVerificationEndpointFilter deviceVerificationEndpointFilter = OAuth2DeviceVerificationEndpointFilter deviceVerificationEndpointFilter =
new OAuth2DeviceVerificationEndpointFilter( new OAuth2DeviceVerificationEndpointFilter(authenticationManager, deviceVerificationEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getDeviceVerificationEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.deviceVerificationRequestConverters.isEmpty()) { if (!this.deviceVerificationRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.deviceVerificationRequestConverters); authenticationConverters.addAll(0, this.deviceVerificationRequestConverters);

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

@ -56,7 +56,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Token Endpoint. * Configurer for the OAuth 2.0 Token Endpoint.
@ -166,8 +166,10 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
this.requestMatcher = new AntPathRequestMatcher( String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuerPattern(authorizationServerSettings.getTokenEndpoint()), HttpMethod.POST.name()); withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) :
authorizationServerSettings.getTokenEndpoint();
this.requestMatcher = new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name());
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
if (!this.authenticationProviders.isEmpty()) { if (!this.authenticationProviders.isEmpty()) {
@ -183,10 +185,11 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) :
authorizationServerSettings.getTokenEndpoint();
OAuth2TokenEndpointFilter tokenEndpointFilter = OAuth2TokenEndpointFilter tokenEndpointFilter =
new OAuth2TokenEndpointFilter( new OAuth2TokenEndpointFilter(authenticationManager, tokenEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getTokenEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.accessTokenRequestConverters.isEmpty()) { if (!this.accessTokenRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.accessTokenRequestConverters); authenticationConverters.addAll(0, this.accessTokenRequestConverters);

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

@ -43,7 +43,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Token Introspection Endpoint. * Configurer for the OAuth 2.0 Token Introspection Endpoint.
@ -153,8 +153,10 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
this.requestMatcher = new AntPathRequestMatcher( String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuerPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()), HttpMethod.POST.name()); withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) :
authorizationServerSettings.getTokenIntrospectionEndpoint();
this.requestMatcher = new AntPathRequestMatcher(tokenIntrospectionEndpointUri, HttpMethod.POST.name());
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
if (!this.authenticationProviders.isEmpty()) { if (!this.authenticationProviders.isEmpty()) {
@ -169,10 +171,11 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA
void configure(HttpSecurity httpSecurity) { void configure(HttpSecurity httpSecurity) {
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) :
authorizationServerSettings.getTokenIntrospectionEndpoint();
OAuth2TokenIntrospectionEndpointFilter introspectionEndpointFilter = OAuth2TokenIntrospectionEndpointFilter introspectionEndpointFilter =
new OAuth2TokenIntrospectionEndpointFilter( new OAuth2TokenIntrospectionEndpointFilter(authenticationManager, tokenIntrospectionEndpointUri);
authenticationManager, withMultipleIssuerPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.introspectionRequestConverters.isEmpty()) { if (!this.introspectionRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.introspectionRequestConverters); authenticationConverters.addAll(0, this.introspectionRequestConverters);

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

@ -42,7 +42,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for the OAuth 2.0 Token Revocation Endpoint. * Configurer for the OAuth 2.0 Token Revocation Endpoint.
@ -152,8 +152,10 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
this.requestMatcher = new AntPathRequestMatcher( String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuerPattern(authorizationServerSettings.getTokenRevocationEndpoint()), HttpMethod.POST.name()); withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) :
authorizationServerSettings.getTokenRevocationEndpoint();
this.requestMatcher = new AntPathRequestMatcher(tokenRevocationEndpointUri, HttpMethod.POST.name());
List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); List<AuthenticationProvider> authenticationProviders = createDefaultAuthenticationProviders(httpSecurity);
if (!this.authenticationProviders.isEmpty()) { if (!this.authenticationProviders.isEmpty()) {
@ -169,9 +171,11 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) :
authorizationServerSettings.getTokenRevocationEndpoint();
OAuth2TokenRevocationEndpointFilter revocationEndpointFilter = OAuth2TokenRevocationEndpointFilter revocationEndpointFilter =
new OAuth2TokenRevocationEndpointFilter( new OAuth2TokenRevocationEndpointFilter(authenticationManager, tokenRevocationEndpointUri);
authenticationManager, withMultipleIssuerPattern(authorizationServerSettings.getTokenRevocationEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.revocationRequestConverters.isEmpty()) { if (!this.revocationRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.revocationRequestConverters); authenticationConverters.addAll(0, this.revocationRequestConverters);

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

@ -46,7 +46,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for OpenID Connect 1.0 Dynamic Client Registration Endpoint. * Configurer for OpenID Connect 1.0 Dynamic Client Registration Endpoint.
@ -162,7 +162,9 @@ public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAut
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String clientRegistrationEndpointUri = withMultipleIssuerPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()); String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) :
authorizationServerSettings.getOidcClientRegistrationEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.POST.name()), new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.POST.name()),
new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.GET.name()) new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.GET.name())
@ -182,10 +184,11 @@ public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAut
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) :
authorizationServerSettings.getOidcClientRegistrationEndpoint();
OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter = OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter =
new OidcClientRegistrationEndpointFilter( new OidcClientRegistrationEndpointFilter(authenticationManager, clientRegistrationEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.clientRegistrationRequestConverters.isEmpty()) { if (!this.clientRegistrationRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.clientRegistrationRequestConverters); authenticationConverters.addAll(0, this.clientRegistrationRequestConverters);

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

@ -44,7 +44,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for OpenID Connect 1.0 RP-Initiated Logout Endpoint. * Configurer for OpenID Connect 1.0 RP-Initiated Logout Endpoint.
@ -153,7 +153,9 @@ public final class OidcLogoutEndpointConfigurer extends AbstractOAuth2Configurer
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String logoutEndpointUri = withMultipleIssuerPattern(authorizationServerSettings.getOidcLogoutEndpoint()); String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) :
authorizationServerSettings.getOidcLogoutEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.GET.name()),
new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.POST.name()) new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.POST.name())
@ -173,10 +175,11 @@ public final class OidcLogoutEndpointConfigurer extends AbstractOAuth2Configurer
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) :
authorizationServerSettings.getOidcLogoutEndpoint();
OidcLogoutEndpointFilter oidcLogoutEndpointFilter = OidcLogoutEndpointFilter oidcLogoutEndpointFilter =
new OidcLogoutEndpointFilter( new OidcLogoutEndpointFilter(authenticationManager, logoutEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getOidcLogoutEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.logoutRequestConverters.isEmpty()) { if (!this.logoutRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.logoutRequestConverters); authenticationConverters.addAll(0, this.logoutRequestConverters);

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

@ -22,6 +22,7 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.authorization.oidc.OidcProviderConfiguration; import org.springframework.security.oauth2.server.authorization.oidc.OidcProviderConfiguration;
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter; import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
@ -69,8 +70,11 @@ public final class OidcProviderConfigurationEndpointConfigurer extends AbstractO
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
this.requestMatcher = new AntPathRequestMatcher( AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
"/**/.well-known/openid-configuration", HttpMethod.GET.name()); String oidcProviderConfigurationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
"/**/.well-known/openid-configuration" :
"/.well-known/openid-configuration";
this.requestMatcher = new AntPathRequestMatcher(oidcProviderConfigurationEndpointUri, HttpMethod.GET.name());
} }
@Override @Override

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

@ -49,7 +49,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuerPattern; import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2ConfigurerUtils.withMultipleIssuersPattern;
/** /**
* Configurer for OpenID Connect 1.0 UserInfo Endpoint. * Configurer for OpenID Connect 1.0 UserInfo Endpoint.
@ -187,7 +187,9 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
@Override @Override
void init(HttpSecurity httpSecurity) { void init(HttpSecurity httpSecurity) {
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String userInfoEndpointUri = withMultipleIssuerPattern(authorizationServerSettings.getOidcUserInfoEndpoint()); String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) :
authorizationServerSettings.getOidcUserInfoEndpoint();
this.requestMatcher = new OrRequestMatcher( this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.GET.name()),
new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.POST.name())); new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.POST.name()));
@ -206,10 +208,11 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class);
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ?
withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) :
authorizationServerSettings.getOidcUserInfoEndpoint();
OidcUserInfoEndpointFilter oidcUserInfoEndpointFilter = OidcUserInfoEndpointFilter oidcUserInfoEndpointFilter =
new OidcUserInfoEndpointFilter( new OidcUserInfoEndpointFilter(authenticationManager, userInfoEndpointUri);
authenticationManager,
withMultipleIssuerPattern(authorizationServerSettings.getOidcUserInfoEndpoint()));
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters(); List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.userInfoRequestConverters.isEmpty()) { if (!this.userInfoRequestConverters.isEmpty()) {
authenticationConverters.addAll(0, this.userInfoRequestConverters); authenticationConverters.addAll(0, this.userInfoRequestConverters);

2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java

@ -32,7 +32,7 @@ public interface AuthorizationServerContext {
* resolves the issuer identifier from the <i>"current"</i> request. * resolves the issuer identifier from the <i>"current"</i> request.
* *
* <p> * <p>
* The issuer identifier may contain a path component to support multiple issuers per host in a multi-tenant hosting configuration. * The issuer identifier may contain a path component to support {@link AuthorizationServerSettings#isMultipleIssuersAllowed() multiple issuers per host} in a multi-tenant hosting configuration.
* *
* <p> * <p>
* For example: * For example:

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

@ -57,11 +57,9 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
/** /**
* The default endpoint {@code URI} for OpenID Provider Configuration requests. * The default endpoint {@code URI} for OpenID Provider Configuration requests.
*/ */
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/**/.well-known/openid-configuration"; private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
private final RequestMatcher requestMatcher = new AntPathRequestMatcher( private final RequestMatcher requestMatcher = createRequestMatcher();
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI,
HttpMethod.GET.name());
private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter = private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter =
new OidcProviderConfigurationHttpMessageConverter(); new OidcProviderConfigurationHttpMessageConverter();
private Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer = (providerConfiguration) -> {}; private Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer = (providerConfiguration) -> {};
@ -123,6 +121,17 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
providerConfiguration.build(), MediaType.APPLICATION_JSON, httpResponse); providerConfiguration.build(), MediaType.APPLICATION_JSON, httpResponse);
} }
private static RequestMatcher createRequestMatcher() {
final RequestMatcher defaultRequestMatcher = new AntPathRequestMatcher(
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI, HttpMethod.GET.name());
final RequestMatcher multipleIssuersRequestMatcher = new AntPathRequestMatcher(
"/**" + DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI, HttpMethod.GET.name());
return (request) ->
AuthorizationServerContextHolder.getContext().getAuthorizationServerSettings().isMultipleIssuersAllowed() ?
multipleIssuersRequestMatcher.matches(request) :
defaultRequestMatcher.matches(request);
}
private static Consumer<List<String>> clientAuthenticationMethods() { private static Consumer<List<String>> clientAuthenticationMethods() {
return (authenticationMethods) -> { return (authenticationMethods) -> {
authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()); authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue());

55
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2020-2023 the original author or authors. * Copyright 2020-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@ package org.springframework.security.oauth2.server.authorization.settings;
import java.util.Map; import java.util.Map;
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContext;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -43,6 +44,25 @@ public final class AuthorizationServerSettings extends AbstractSettings {
return getSetting(ConfigurationSettingNames.AuthorizationServer.ISSUER); return getSetting(ConfigurationSettingNames.AuthorizationServer.ISSUER);
} }
/**
* Returns {@code true} if multiple issuers are allowed per host. The default is {@code false}.
* Using path components in the URL of the issuer identifier enables supporting multiple issuers per host in a multi-tenant hosting configuration.
*
* <p>
* For example:
* <ul>
* <li>{@code https://example.com/issuer1}</li>
* <li>{@code https://example.com/authz/issuer2}</li>
* </ul>
*
* @return {@code true} if multiple issuers are allowed per host, {@code false} otherwise
* @since 1.3
* @see AuthorizationServerContext#getIssuer()
*/
public boolean isMultipleIssuersAllowed() {
return getSetting(ConfigurationSettingNames.AuthorizationServer.MULTIPLE_ISSUERS_ALLOWED);
}
/** /**
* Returns the OAuth 2.0 Authorization endpoint. The default is {@code /oauth2/authorize}. * Returns the OAuth 2.0 Authorization endpoint. The default is {@code /oauth2/authorize}.
* *
@ -143,6 +163,7 @@ public final class AuthorizationServerSettings extends AbstractSettings {
*/ */
public static Builder builder() { public static Builder builder() {
return new Builder() return new Builder()
.multipleIssuersAllowed(false)
.authorizationEndpoint("/oauth2/authorize") .authorizationEndpoint("/oauth2/authorize")
.deviceAuthorizationEndpoint("/oauth2/device_authorization") .deviceAuthorizationEndpoint("/oauth2/device_authorization")
.deviceVerificationEndpoint("/oauth2/device_verification") .deviceVerificationEndpoint("/oauth2/device_verification")
@ -185,6 +206,31 @@ public final class AuthorizationServerSettings extends AbstractSettings {
return setting(ConfigurationSettingNames.AuthorizationServer.ISSUER, issuer); return setting(ConfigurationSettingNames.AuthorizationServer.ISSUER, issuer);
} }
/**
* Set to {@code true} if multiple issuers are allowed per host.
* Using path components in the URL of the issuer identifier enables supporting multiple issuers per host in a multi-tenant hosting configuration.
*
* <p>
* For example:
* <ul>
* <li>{@code https://example.com/issuer1}</li>
* <li>{@code https://example.com/authz/issuer2}</li>
* </ul>
*
* <p>
* <b>NOTE:</b> Explicitly configuring the issuer identifier via {@link #issuer(String)} forces to a single-tenant configuration.
* Avoid configuring the issuer identifier when using a multi-tenant hosting configuration,
* allowing the issuer identifier to be resolved from the <i>"current"</i> request.
*
* @param multipleIssuersAllowed {@code true} if multiple issuers are allowed per host, {@code false} otherwise
* @return the {@link Builder} for further configuration
* @since 1.3
* @see AuthorizationServerContext#getIssuer()
*/
public Builder multipleIssuersAllowed(boolean multipleIssuersAllowed) {
return setting(ConfigurationSettingNames.AuthorizationServer.MULTIPLE_ISSUERS_ALLOWED, multipleIssuersAllowed);
}
/** /**
* Sets the OAuth 2.0 Authorization endpoint. * Sets the OAuth 2.0 Authorization endpoint.
* *
@ -295,7 +341,12 @@ public final class AuthorizationServerSettings extends AbstractSettings {
*/ */
@Override @Override
public AuthorizationServerSettings build() { public AuthorizationServerSettings build() {
return new AuthorizationServerSettings(getSettings()); AuthorizationServerSettings authorizationServerSettings = new AuthorizationServerSettings(getSettings());
if (authorizationServerSettings.getIssuer() != null && authorizationServerSettings.isMultipleIssuersAllowed()) {
throw new IllegalArgumentException("The issuer identifier (" + authorizationServerSettings.getIssuer() +
") cannot be set when isMultipleIssuersAllowed() is true.");
}
return authorizationServerSettings;
} }
} }

6
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java

@ -88,6 +88,12 @@ public final class ConfigurationSettingNames {
*/ */
public static final String ISSUER = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE.concat("issuer"); public static final String ISSUER = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE.concat("issuer");
/**
* Set to {@code true} if multiple issuers are allowed per host.
* @since 1.3
*/
public static final String MULTIPLE_ISSUERS_ALLOWED = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE.concat("multiple-issuers-allowed");
/** /**
* Set the OAuth 2.0 Authorization endpoint. * Set the OAuth 2.0 Authorization endpoint.
*/ */

17
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java

@ -55,11 +55,9 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
/** /**
* The default endpoint {@code URI} for OAuth 2.0 Authorization Server Metadata requests. * The default endpoint {@code URI} for OAuth 2.0 Authorization Server Metadata requests.
*/ */
private static final String DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI = "/.well-known/oauth-authorization-server/**"; private static final String DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI = "/.well-known/oauth-authorization-server";
private final RequestMatcher requestMatcher = new AntPathRequestMatcher( private final RequestMatcher requestMatcher = createRequestMatcher();
DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI,
HttpMethod.GET.name());
private final OAuth2AuthorizationServerMetadataHttpMessageConverter authorizationServerMetadataHttpMessageConverter = private final OAuth2AuthorizationServerMetadataHttpMessageConverter authorizationServerMetadataHttpMessageConverter =
new OAuth2AuthorizationServerMetadataHttpMessageConverter(); new OAuth2AuthorizationServerMetadataHttpMessageConverter();
private Consumer<OAuth2AuthorizationServerMetadata.Builder> authorizationServerMetadataCustomizer = (authorizationServerMetadata) -> {}; private Consumer<OAuth2AuthorizationServerMetadata.Builder> authorizationServerMetadataCustomizer = (authorizationServerMetadata) -> {};
@ -116,6 +114,17 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
authorizationServerMetadata.build(), MediaType.APPLICATION_JSON, httpResponse); authorizationServerMetadata.build(), MediaType.APPLICATION_JSON, httpResponse);
} }
private static RequestMatcher createRequestMatcher() {
final RequestMatcher defaultRequestMatcher = new AntPathRequestMatcher(
DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI, HttpMethod.GET.name());
final RequestMatcher multipleIssuersRequestMatcher = new AntPathRequestMatcher(
DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI + "/**", HttpMethod.GET.name());
return (request) ->
AuthorizationServerContextHolder.getContext().getAuthorizationServerSettings().isMultipleIssuersAllowed() ?
multipleIssuersRequestMatcher.matches(request) :
defaultRequestMatcher.matches(request);
}
private static Consumer<List<String>> clientAuthenticationMethods() { private static Consumer<List<String>> clientAuthenticationMethods() {
return (authenticationMethods) -> { return (authenticationMethods) -> {
authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()); authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue());

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

@ -63,7 +63,6 @@ public class JwkSetTests {
private static final String DEFAULT_JWK_SET_ENDPOINT_URI = "/oauth2/jwks"; private static final String DEFAULT_JWK_SET_ENDPOINT_URI = "/oauth2/jwks";
private static EmbeddedDatabase db; private static EmbeddedDatabase db;
private static JWKSource<SecurityContext> jwkSource; private static JWKSource<SecurityContext> jwkSource;
private static AuthorizationServerSettings authorizationServerSettings;
public final SpringTestContext spring = new SpringTestContext(); public final SpringTestContext spring = new SpringTestContext();
@ -73,11 +72,13 @@ public class JwkSetTests {
@Autowired @Autowired
private JdbcOperations jdbcOperations; private JdbcOperations jdbcOperations;
@Autowired
private AuthorizationServerSettings authorizationServerSettings;
@BeforeAll @BeforeAll
public static void init() { public static void init() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK); JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
authorizationServerSettings = AuthorizationServerSettings.builder().jwkSetEndpoint("/test/jwks").build();
db = new EmbeddedDatabaseBuilder() db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true) .generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL) .setType(EmbeddedDatabaseType.HSQL)
@ -181,7 +182,7 @@ public class JwkSetTests {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return authorizationServerSettings; return AuthorizationServerSettings.builder().jwkSetEndpoint("/test/jwks").multipleIssuersAllowed(true).build();
} }
} }

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

@ -857,7 +857,7 @@ public class OAuth2AuthorizationCodeGrantTests {
@Test @Test
public void requestWhenAuthorizationAndTokenRequestIncludesIssuerPathThenIssuerResolvedWithPath() throws Exception { public void requestWhenAuthorizationAndTokenRequestIncludesIssuerPathThenIssuerResolvedWithPath() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithTokenGenerator.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredPublicClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredPublicClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
@ -1260,4 +1260,15 @@ public class OAuth2AuthorizationCodeGrantTests {
// @formatter:on // @formatter:on
} }
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfigurationWithTokenGenerator {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}
} }

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

@ -113,7 +113,7 @@ public class OAuth2AuthorizationServerMetadataTests {
@Test @Test
public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath() throws Exception { public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithIssuerNotSet.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
String host = "https://example.com:8443"; String host = "https://example.com:8443";
@ -216,11 +216,11 @@ public class OAuth2AuthorizationServerMetadataTests {
@EnableWebSecurity @EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class) @Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithIssuerNotSet extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build(); return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
} }
} }

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

@ -84,6 +84,7 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients; import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin; import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContext; import org.springframework.security.oauth2.server.authorization.test.SpringTestContext;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension; import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension;
@ -398,7 +399,7 @@ public class OAuth2ClientCredentialsGrantTests {
@Test @Test
public void requestWhenTokenRequestIncludesIssuerPathThenIssuerResolvedWithPath() throws Exception { public void requestWhenTokenRequestIncludesIssuerPathThenIssuerResolvedWithPath() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
@ -573,4 +574,15 @@ public class OAuth2ClientCredentialsGrantTests {
} }
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}
} }

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

@ -70,6 +70,7 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients; import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContext; import org.springframework.security.oauth2.server.authorization.test.SpringTestContext;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension; import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
@ -204,7 +205,7 @@ public class OAuth2DeviceCodeGrantTests {
@Test @Test
public void requestWhenDeviceAuthorizationRequestValidThenReturnDeviceAuthorizationResponse() throws Exception { public void requestWhenDeviceAuthorizationRequestValidThenReturnDeviceAuthorizationResponse() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
// @formatter:off // @formatter:off
RegisteredClient registeredClient = TestRegisteredClients.registeredClient() RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
@ -288,7 +289,7 @@ public class OAuth2DeviceCodeGrantTests {
@Test @Test
public void requestWhenDeviceVerificationRequestValidThenDisplaysConsentPage() throws Exception { public void requestWhenDeviceVerificationRequestValidThenDisplaysConsentPage() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
// @formatter:off // @formatter:off
RegisteredClient registeredClient = TestRegisteredClients.registeredClient() RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
@ -585,4 +586,15 @@ public class OAuth2DeviceCodeGrantTests {
} }
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}
} }

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

@ -123,7 +123,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@ExtendWith(SpringTestContextExtension.class) @ExtendWith(SpringTestContextExtension.class)
public class OAuth2TokenIntrospectionTests { public class OAuth2TokenIntrospectionTests {
private static EmbeddedDatabase db; private static EmbeddedDatabase db;
private static AuthorizationServerSettings authorizationServerSettings;
private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer; private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
private static AuthenticationConverter authenticationConverter; private static AuthenticationConverter authenticationConverter;
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer; private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
@ -150,9 +149,11 @@ public class OAuth2TokenIntrospectionTests {
@Autowired @Autowired
private OAuth2AuthorizationService authorizationService; private OAuth2AuthorizationService authorizationService;
@Autowired
private AuthorizationServerSettings authorizationServerSettings;
@BeforeAll @BeforeAll
public static void init() { public static void init() {
authorizationServerSettings = AuthorizationServerSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
authenticationConverter = mock(AuthenticationConverter.class); authenticationConverter = mock(AuthenticationConverter.class);
authenticationConvertersConsumer = mock(Consumer.class); authenticationConvertersConsumer = mock(Consumer.class);
authenticationProvider = mock(AuthenticationProvider.class); authenticationProvider = mock(AuthenticationProvider.class);
@ -225,7 +226,7 @@ public class OAuth2TokenIntrospectionTests {
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
// @formatter:off // @formatter:off
MvcResult mvcResult = this.mvc.perform(post(authorizationServerSettings.getTokenIntrospectionEndpoint()) MvcResult mvcResult = this.mvc.perform(post(this.authorizationServerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN)) .params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -265,7 +266,7 @@ public class OAuth2TokenIntrospectionTests {
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
// @formatter:off // @formatter:off
MvcResult mvcResult = this.mvc.perform(post(authorizationServerSettings.getTokenIntrospectionEndpoint()) MvcResult mvcResult = this.mvc.perform(post(this.authorizationServerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(refreshToken, OAuth2TokenType.REFRESH_TOKEN)) .params(getTokenIntrospectionRequestParameters(refreshToken, OAuth2TokenType.REFRESH_TOKEN))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -307,7 +308,7 @@ public class OAuth2TokenIntrospectionTests {
this.authorizationService.save(authorization); this.authorizationService.save(authorization);
// @formatter:off // @formatter:off
MvcResult mvcResult = this.mvc.perform(post(authorizationServerSettings.getTokenEndpoint()) MvcResult mvcResult = this.mvc.perform(post(this.authorizationServerSettings.getTokenEndpoint())
.params(getAuthorizationCodeTokenRequestParameters(authorizedRegisteredClient, authorization)) .params(getAuthorizationCodeTokenRequestParameters(authorizedRegisteredClient, authorization))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(authorizedRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(authorizedRegisteredClient)))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -321,7 +322,7 @@ public class OAuth2TokenIntrospectionTests {
this.registeredClientRepository.save(introspectRegisteredClient); this.registeredClientRepository.save(introspectRegisteredClient);
// @formatter:off // @formatter:off
mvcResult = this.mvc.perform(post(authorizationServerSettings.getTokenIntrospectionEndpoint()) mvcResult = this.mvc.perform(post(this.authorizationServerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN)) .params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
.andExpect(status().isOk()) .andExpect(status().isOk())
@ -380,7 +381,7 @@ public class OAuth2TokenIntrospectionTests {
when(authenticationProvider.authenticate(any())).thenReturn(tokenIntrospectionAuthentication); when(authenticationProvider.authenticate(any())).thenReturn(tokenIntrospectionAuthentication);
// @formatter:off // @formatter:off
this.mvc.perform(post(authorizationServerSettings.getTokenIntrospectionEndpoint()) this.mvc.perform(post(this.authorizationServerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN)) .params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
.andExpect(status().isOk()); .andExpect(status().isOk());
@ -437,7 +438,7 @@ public class OAuth2TokenIntrospectionTests {
String issuer = "https://example.com:8443/issuer1"; String issuer = "https://example.com:8443/issuer1";
// @formatter:off // @formatter:off
this.mvc.perform(post(issuer.concat(authorizationServerSettings.getTokenIntrospectionEndpoint())) this.mvc.perform(post(issuer.concat(this.authorizationServerSettings.getTokenIntrospectionEndpoint()))
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN)) .params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient))) .header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(introspectRegisteredClient)))
.andExpect(status().isOk()); .andExpect(status().isOk());
@ -517,7 +518,7 @@ public class OAuth2TokenIntrospectionTests {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return authorizationServerSettings; return AuthorizationServerSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
} }
@Bean @Bean
@ -581,6 +582,12 @@ public class OAuth2TokenIntrospectionTests {
} }
// @formatter:on // @formatter:on
@Override
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).tokenIntrospectionEndpoint("/test/introspect").build();
}
} }
} }

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

@ -69,6 +69,7 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients; import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin; import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContext; import org.springframework.security.oauth2.server.authorization.test.SpringTestContext;
import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension; import org.springframework.security.oauth2.server.authorization.test.SpringTestContextExtension;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter; import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
@ -203,7 +204,7 @@ public class OAuth2TokenRevocationTests {
@Test @Test
public void requestWhenRevokeAccessTokenAndRequestIncludesIssuerPathThenRevoked() throws Exception { public void requestWhenRevokeAccessTokenAndRequestIncludesIssuerPathThenRevoked() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
this.registeredClientRepository.save(registeredClient); this.registeredClientRepository.save(registeredClient);
@ -383,4 +384,15 @@ public class OAuth2TokenRevocationTests {
} }
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
}
}
} }

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

@ -735,6 +735,7 @@ public class OidcClientRegistrationTests {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder() return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build(); .build();
} }

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

@ -84,7 +84,7 @@ public class OidcProviderConfigurationTests {
@Test @Test
public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath() throws Exception { public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithIssuerNotSet.class).autowire(); this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire();
String issuer = "https://example.com:8443/issuer1"; String issuer = "https://example.com:8443/issuer1";
this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
@ -219,6 +219,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfiguration { static class AuthorizationServerConfiguration {
@Bean @Bean
@ -245,11 +246,13 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
static class AuthorizationServerConfigurationWithIssuerNotSet extends AuthorizationServerConfiguration { @Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder() return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build(); .build();
} }
@ -315,6 +318,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithInvalidIssuerUrl extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithInvalidIssuerUrl extends AuthorizationServerConfiguration {
@Bean @Bean
@ -324,6 +328,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithInvalidIssuerUri extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithInvalidIssuerUri extends AuthorizationServerConfiguration {
@Bean @Bean
@ -333,6 +338,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithIssuerQuery extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithIssuerQuery extends AuthorizationServerConfiguration {
@Bean @Bean
@ -342,6 +348,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithIssuerFragment extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithIssuerFragment extends AuthorizationServerConfiguration {
@Bean @Bean
@ -351,6 +358,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithIssuerQueryAndFragment extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithIssuerQueryAndFragment extends AuthorizationServerConfiguration {
@Bean @Bean
@ -360,6 +368,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithIssuerEmptyQuery extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithIssuerEmptyQuery extends AuthorizationServerConfiguration {
@Bean @Bean
@ -369,6 +378,7 @@ public class OidcProviderConfigurationTests {
} }
@EnableWebSecurity @EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithIssuerEmptyFragment extends AuthorizationServerConfiguration { static class AuthorizationServerConfigurationWithIssuerEmptyFragment extends AuthorizationServerConfiguration {
@Bean @Bean

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

@ -617,7 +617,7 @@ public class OidcTests {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build(); return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
} }
@Bean @Bean

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

@ -531,6 +531,7 @@ public class OidcUserInfoTests {
@Bean @Bean
AuthorizationServerSettings authorizationServerSettings() { AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder() return AuthorizationServerSettings.builder()
.multipleIssuersAllowed(true)
.build(); .build();
} }

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

@ -18,6 +18,7 @@ package org.springframework.security.oauth2.server.authorization.oidc.web;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -60,6 +61,9 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test @Test
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception { public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = "/path"; String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
request.setServletPath(requestUri); request.setServletPath(requestUri);
@ -73,6 +77,9 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test @Test
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception { public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI; String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
request.setServletPath(requestUri); request.setServletPath(requestUri);

30
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2020-2023 the original author or authors. * Copyright 2020-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,6 +33,7 @@ public class AuthorizationServerSettingsTests {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().build(); AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().build();
assertThat(authorizationServerSettings.getIssuer()).isNull(); assertThat(authorizationServerSettings.getIssuer()).isNull();
assertThat(authorizationServerSettings.isMultipleIssuersAllowed()).isFalse();
assertThat(authorizationServerSettings.getAuthorizationEndpoint()).isEqualTo("/oauth2/authorize"); assertThat(authorizationServerSettings.getAuthorizationEndpoint()).isEqualTo("/oauth2/authorize");
assertThat(authorizationServerSettings.getTokenEndpoint()).isEqualTo("/oauth2/token"); assertThat(authorizationServerSettings.getTokenEndpoint()).isEqualTo("/oauth2/token");
assertThat(authorizationServerSettings.getJwkSetEndpoint()).isEqualTo("/oauth2/jwks"); assertThat(authorizationServerSettings.getJwkSetEndpoint()).isEqualTo("/oauth2/jwks");
@ -69,6 +70,7 @@ public class AuthorizationServerSettingsTests {
.build(); .build();
assertThat(authorizationServerSettings.getIssuer()).isEqualTo(issuer); assertThat(authorizationServerSettings.getIssuer()).isEqualTo(issuer);
assertThat(authorizationServerSettings.isMultipleIssuersAllowed()).isFalse();
assertThat(authorizationServerSettings.getAuthorizationEndpoint()).isEqualTo(authorizationEndpoint); assertThat(authorizationServerSettings.getAuthorizationEndpoint()).isEqualTo(authorizationEndpoint);
assertThat(authorizationServerSettings.getTokenEndpoint()).isEqualTo(tokenEndpoint); assertThat(authorizationServerSettings.getTokenEndpoint()).isEqualTo(tokenEndpoint);
assertThat(authorizationServerSettings.getJwkSetEndpoint()).isEqualTo(jwkSetEndpoint); assertThat(authorizationServerSettings.getJwkSetEndpoint()).isEqualTo(jwkSetEndpoint);
@ -79,6 +81,30 @@ public class AuthorizationServerSettingsTests {
assertThat(authorizationServerSettings.getOidcLogoutEndpoint()).isEqualTo(oidcLogoutEndpoint); assertThat(authorizationServerSettings.getOidcLogoutEndpoint()).isEqualTo(oidcLogoutEndpoint);
} }
@Test
public void buildWhenIssuerSetAndMultipleIssuersAllowedTrueThenThrowIllegalArgumentException() {
String issuer = "https://example.com:9000";
assertThatIllegalArgumentException()
.isThrownBy(() -> AuthorizationServerSettings.builder().issuer(issuer).multipleIssuersAllowed(true).build())
.withMessage("The issuer identifier (" + issuer + ") cannot be set when isMultipleIssuersAllowed() is true.");
}
@Test
public void buildWhenIssuerNotSetAndMultipleIssuersAllowedTrueThenDefaultsAreSet() {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();
assertThat(authorizationServerSettings.getIssuer()).isNull();
assertThat(authorizationServerSettings.isMultipleIssuersAllowed()).isTrue();
assertThat(authorizationServerSettings.getAuthorizationEndpoint()).isEqualTo("/oauth2/authorize");
assertThat(authorizationServerSettings.getTokenEndpoint()).isEqualTo("/oauth2/token");
assertThat(authorizationServerSettings.getJwkSetEndpoint()).isEqualTo("/oauth2/jwks");
assertThat(authorizationServerSettings.getTokenRevocationEndpoint()).isEqualTo("/oauth2/revoke");
assertThat(authorizationServerSettings.getTokenIntrospectionEndpoint()).isEqualTo("/oauth2/introspect");
assertThat(authorizationServerSettings.getOidcClientRegistrationEndpoint()).isEqualTo("/connect/register");
assertThat(authorizationServerSettings.getOidcUserInfoEndpoint()).isEqualTo("/userinfo");
assertThat(authorizationServerSettings.getOidcLogoutEndpoint()).isEqualTo("/connect/logout");
}
@Test @Test
public void settingWhenCustomThenSet() { public void settingWhenCustomThenSet() {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder() AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
@ -86,7 +112,7 @@ public class AuthorizationServerSettingsTests {
.settings(settings -> settings.put("name2", "value2")) .settings(settings -> settings.put("name2", "value2"))
.build(); .build();
assertThat(authorizationServerSettings.getSettings()).hasSize(12); assertThat(authorizationServerSettings.getSettings()).hasSize(13);
assertThat(authorizationServerSettings.<String>getSetting("name1")).isEqualTo("value1"); assertThat(authorizationServerSettings.<String>getSetting("name1")).isEqualTo("value1");
assertThat(authorizationServerSettings.<String>getSetting("name2")).isEqualTo("value2"); assertThat(authorizationServerSettings.<String>getSetting("name2")).isEqualTo("value2");
} }

7
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java

@ -18,6 +18,7 @@ package org.springframework.security.oauth2.server.authorization.web;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -60,6 +61,9 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test @Test
public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception { public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = "/path"; String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
request.setServletPath(requestUri); request.setServletPath(requestUri);
@ -73,6 +77,9 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test @Test
public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception { public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception {
AuthorizationServerContextHolder.setContext(
new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null));
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI; String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
request.setServletPath(requestUri); request.setServletPath(requestUri);

2
samples/demo-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

@ -93,7 +93,7 @@ public class AuthorizationServerConfig {
*/ */
DeviceClientAuthenticationConverter deviceClientAuthenticationConverter = DeviceClientAuthenticationConverter deviceClientAuthenticationConverter =
new DeviceClientAuthenticationConverter( new DeviceClientAuthenticationConverter(
"/**" + authorizationServerSettings.getDeviceAuthorizationEndpoint()); authorizationServerSettings.getDeviceAuthorizationEndpoint());
DeviceClientAuthenticationProvider deviceClientAuthenticationProvider = DeviceClientAuthenticationProvider deviceClientAuthenticationProvider =
new DeviceClientAuthenticationProvider(registeredClientRepository); new DeviceClientAuthenticationProvider(registeredClientRepository);

Loading…
Cancel
Save