Merge branch 0.4.x into main

The following commits are merged using the default merge strategy.

70d433a45a Update ref-doc with OAuth2Authorization.getAuthorizedScopes()
0994a1e1e1 Allow customizing OIDC Provider Configuration Response
8043b8c949 Allow customizing Authorization Server Metadata Response
4466cbe69d Use configured ID Token signature algorithm
502fa24cfb Polish gh-787
07d69cbfb4 Validate client secret not expired
2cc603c7e7 Improve configurability for AuthenticationConverter and AuthenticationProvider
1db05991af Make OAuth2AuthenticationContext an interface
c326b1a2ba Remove OAuth2AuthenticationValidator
This commit is contained in:
Joe Grandja
2022-09-13 04:36:21 -04:00
38 changed files with 1653 additions and 577 deletions

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.security.oauth2.server.authorization.authentication;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
@@ -182,6 +184,26 @@ public class ClientSecretAuthenticationProviderTests {
verify(this.passwordEncoder).matches(any(), any());
}
@Test
public void authenticateWhenExpiredClientSecretThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSecretExpiresAt(Instant.now().minus(1, ChronoUnit.HOURS).truncatedTo(ChronoUnit.SECONDS))
.build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret(), null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
.satisfies(error -> {
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
assertThat(error.getDescription()).contains("client_secret_expires_at");
});
verify(this.passwordEncoder).matches(any(), any());
}
@Test
public void authenticateWhenValidCredentialsThenAuthenticated() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();

View File

@@ -22,7 +22,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import org.junit.Before;
import org.junit.Test;
@@ -60,7 +59,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -128,10 +126,10 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
}
@Test
public void setAuthenticationValidatorResolverWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authenticationProvider.setAuthenticationValidatorResolver(null))
public void setAuthenticationValidatorWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.authenticationProvider.setAuthenticationValidator(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authenticationValidatorResolver cannot be null");
.hasMessage("authenticationValidator cannot be null");
}
@Test
@@ -555,14 +553,14 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
}
@Test
public void authenticateWhenCustomAuthenticationValidatorResolverThenUsed() {
public void authenticateWhenCustomAuthenticationValidatorThenUsed() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
@SuppressWarnings("unchecked")
Function<String, OAuth2AuthenticationValidator> authenticationValidatorResolver = mock(Function.class);
this.authenticationProvider.setAuthenticationValidatorResolver(authenticationValidatorResolver);
Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authenticationValidator = mock(Consumer.class);
this.authenticationProvider.setAuthenticationValidator(authenticationValidator);
OAuth2AuthorizationCodeRequestAuthenticationToken authentication =
authorizationCodeRequestAuthentication(registeredClient, this.principal)
@@ -573,10 +571,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
assertAuthorizationCodeRequestWithAuthorizationCodeResult(registeredClient, authentication, authenticationResult);
ArgumentCaptor<String> parameterNameCaptor = ArgumentCaptor.forClass(String.class);
verify(authenticationValidatorResolver, times(2)).apply(parameterNameCaptor.capture());
assertThat(parameterNameCaptor.getAllValues()).containsExactly(
OAuth2ParameterNames.REDIRECT_URI, OAuth2ParameterNames.SCOPE);
verify(authenticationValidator).accept(any());
}
private void assertAuthorizationCodeRequestWithAuthorizationCodeResult(

View File

@@ -107,6 +107,7 @@ import org.springframework.security.oauth2.server.authorization.token.OAuth2Refr
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
@@ -165,7 +166,9 @@ public class OAuth2AuthorizationCodeGrantTests {
private static HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
private static AuthenticationConverter authorizationRequestConverter;
private static Consumer<List<AuthenticationConverter>> authorizationRequestConvertersConsumer;
private static AuthenticationProvider authorizationRequestAuthenticationProvider;
private static Consumer<List<AuthenticationProvider>> authorizationRequestAuthenticationProvidersConsumer;
private static AuthenticationSuccessHandler authorizationResponseHandler;
private static AuthenticationFailureHandler authorizationErrorResponseHandler;
private static SecurityContextRepository securityContextRepository;
@@ -202,7 +205,9 @@ public class OAuth2AuthorizationCodeGrantTests {
.tokenEndpoint("/test/token")
.build();
authorizationRequestConverter = mock(AuthenticationConverter.class);
authorizationRequestConvertersConsumer = mock(Consumer.class);
authorizationRequestAuthenticationProvider = mock(AuthenticationProvider.class);
authorizationRequestAuthenticationProvidersConsumer = mock(Consumer.class);
authorizationResponseHandler = mock(AuthenticationSuccessHandler.class);
authorizationErrorResponseHandler = mock(AuthenticationFailureHandler.class);
securityContextRepository = spy(new HttpSessionSecurityContextRepository());
@@ -638,7 +643,25 @@ public class OAuth2AuthorizationCodeGrantTests {
.andExpect(status().isOk());
verify(authorizationRequestConverter).convert(any());
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
verify(authorizationRequestConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authorizationRequestConverter ||
converter instanceof OAuth2AuthorizationCodeRequestAuthenticationConverter);
verify(authorizationRequestAuthenticationProvider).authenticate(eq(authorizationCodeRequestAuthenticationResult));
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
verify(authorizationRequestAuthenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authorizationRequestAuthenticationProvider ||
provider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider);
verify(authorizationResponseHandler).onAuthenticationSuccess(any(), any(), eq(authorizationCodeRequestAuthenticationResult));
}
@@ -998,7 +1021,9 @@ public class OAuth2AuthorizationCodeGrantTests {
.authorizationEndpoint(authorizationEndpoint ->
authorizationEndpoint
.authorizationRequestConverter(authorizationRequestConverter)
.authorizationRequestConverters(authorizationRequestConvertersConsumer)
.authenticationProvider(authorizationRequestAuthenticationProvider)
.authenticationProviders(authorizationRequestAuthenticationProvidersConsumer)
.authorizationResponseHandler(authorizationResponseHandler)
.errorResponseHandler(authorizationErrorResponseHandler));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers;
import java.util.function.Consumer;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
@@ -26,14 +28,18 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.jose.TestJwks;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadata;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadataClaimNames;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
@@ -41,8 +47,11 @@ import org.springframework.security.oauth2.server.authorization.client.TestRegis
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.SpringTestRule;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -111,6 +120,17 @@ public class OAuth2AuthorizationServerMetadataTests {
.andReturn();
}
// gh-616
@Test
public void requestWhenAuthorizationServerMetadataRequestAndMetadataCustomizerSetThenReturnCustomMetadataResponse() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithMetadataCustomizer.class).autowire();
this.mvc.perform(get(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems("scope1", "scope2")));
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfiguration {
@@ -139,6 +159,42 @@ public class OAuth2AuthorizationServerMetadataTests {
}
}
@Configuration
@EnableWebSecurity
static class AuthorizationServerConfigurationWithMetadataCustomizer extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint ->
authorizationServerMetadataEndpoint
.authorizationServerMetadataCustomizer(authorizationServerMetadataCustomizer()));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
http
.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher));
return http.build();
}
// @formatter:on
private Consumer<OAuth2AuthorizationServerMetadata.Builder> authorizationServerMetadataCustomizer() {
return (authorizationServerMetadata) ->
authorizationServerMetadata.scope("scope1").scope("scope2");
}
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithIssuerNotSet extends AuthorizationServerConfiguration {

View File

@@ -21,6 +21,8 @@ import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.Base64;
import java.util.List;
import java.util.function.Consumer;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -35,6 +37,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -60,9 +63,15 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.jose.TestJwks;
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.JwtClientAssertionAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2RefreshTokenAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.PublicClientAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
@@ -73,6 +82,13 @@ import org.springframework.security.oauth2.server.authorization.jackson2.Testing
import org.springframework.security.oauth2.server.authorization.test.SpringTestRule;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretBasicAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.ClientSecretPostAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.JwtClientAssertionAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2ClientCredentialsAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2RefreshTokenAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.PublicClientAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
@@ -81,6 +97,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -104,7 +121,9 @@ public class OAuth2ClientCredentialsGrantTests {
private static JWKSource<SecurityContext> jwkSource;
private static OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;
private static AuthenticationConverter authenticationConverter;
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
private static AuthenticationProvider authenticationProvider;
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
private static AuthenticationSuccessHandler authenticationSuccessHandler;
private static AuthenticationFailureHandler authenticationFailureHandler;
@@ -126,7 +145,9 @@ public class OAuth2ClientCredentialsGrantTests {
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
jwtCustomizer = mock(OAuth2TokenCustomizer.class);
authenticationConverter = mock(AuthenticationConverter.class);
authenticationConvertersConsumer = mock(Consumer.class);
authenticationProvider = mock(AuthenticationProvider.class);
authenticationProvidersConsumer = mock(Consumer.class);
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
db = new EmbeddedDatabaseBuilder()
@@ -143,7 +164,9 @@ public class OAuth2ClientCredentialsGrantTests {
public void setup() {
reset(jwtCustomizer);
reset(authenticationConverter);
reset(authenticationConvertersConsumer);
reset(authenticationProvider);
reset(authenticationProvidersConsumer);
reset(authenticationSuccessHandler);
reset(authenticationFailureHandler);
}
@@ -234,7 +257,29 @@ public class OAuth2ClientCredentialsGrantTests {
.andExpect(status().isOk());
verify(authenticationConverter).convert(any());
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof OAuth2AuthorizationCodeAuthenticationConverter ||
converter instanceof OAuth2RefreshTokenAuthenticationConverter ||
converter instanceof OAuth2ClientCredentialsAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(clientCredentialsAuthentication));
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof OAuth2AuthorizationCodeAuthenticationProvider ||
provider instanceof OAuth2RefreshTokenAuthenticationProvider ||
provider instanceof OAuth2ClientCredentialsAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(accessTokenAuthentication));
}
@@ -246,19 +291,40 @@ public class OAuth2ClientCredentialsGrantTests {
this.registeredClientRepository.save(registeredClient);
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
registeredClient, new ClientAuthenticationMethod("custom"), null);
when(authenticationConverter.convert(any())).thenReturn(clientPrincipal);
when(authenticationProvider.supports(eq(OAuth2ClientAuthenticationToken.class))).thenReturn(true);
when(authenticationProvider.authenticate(any())).thenReturn(clientPrincipal);
this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth(
registeredClient.getClientId(), registeredClient.getClientSecret())))
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()))
.andExpect(status().isOk());
verify(authenticationConverter).convert(any());
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof JwtClientAssertionAuthenticationConverter ||
converter instanceof ClientSecretBasicAuthenticationConverter ||
converter instanceof ClientSecretPostAuthenticationConverter ||
converter instanceof PublicClientAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(clientPrincipal));
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof JwtClientAssertionAuthenticationProvider ||
provider instanceof ClientSecretAuthenticationProvider ||
provider instanceof PublicClientAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(clientPrincipal));
}
@@ -341,7 +407,9 @@ public class OAuth2ClientCredentialsGrantTests {
.tokenEndpoint(tokenEndpoint ->
tokenEndpoint
.accessTokenRequestConverter(authenticationConverter)
.accessTokenRequestConverters(authenticationConvertersConsumer)
.authenticationProvider(authenticationProvider)
.authenticationProviders(authenticationProvidersConsumer)
.accessTokenResponseHandler(authenticationSuccessHandler)
.errorResponseHandler(authenticationFailureHandler));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
@@ -371,7 +439,9 @@ public class OAuth2ClientCredentialsGrantTests {
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationConverter(authenticationConverter)
.authenticationConverters(authenticationConvertersConsumer)
.authenticationProvider(authenticationProvider)
.authenticationProviders(authenticationProvidersConsumer)
.authenticationSuccessHandler(authenticationSuccessHandler)
.errorResponseHandler(authenticationFailureHandler));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

View File

@@ -25,6 +25,7 @@ import java.util.Base64;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.function.Consumer;
import org.junit.After;
import org.junit.AfterClass;
@@ -72,6 +73,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2TokenIntro
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenIntrospectionAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
@@ -88,6 +90,7 @@ import org.springframework.security.oauth2.server.authorization.test.SpringTestR
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimsSet;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenIntrospectionAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
@@ -118,7 +121,9 @@ public class OAuth2TokenIntrospectionTests {
private static AuthorizationServerSettings authorizationServerSettings;
private static OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer;
private static AuthenticationConverter authenticationConverter;
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
private static AuthenticationProvider authenticationProvider;
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
private static AuthenticationSuccessHandler authenticationSuccessHandler;
private static AuthenticationFailureHandler authenticationFailureHandler;
private static final HttpMessageConverter<OAuth2TokenIntrospection> tokenIntrospectionHttpResponseConverter =
@@ -145,7 +150,9 @@ public class OAuth2TokenIntrospectionTests {
public static void init() {
authorizationServerSettings = AuthorizationServerSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
authenticationConverter = mock(AuthenticationConverter.class);
authenticationConvertersConsumer = mock(Consumer.class);
authenticationProvider = mock(AuthenticationProvider.class);
authenticationProvidersConsumer = mock(Consumer.class);
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
accessTokenCustomizer = mock(OAuth2TokenCustomizer.class);
@@ -364,7 +371,25 @@ public class OAuth2TokenIntrospectionTests {
// @formatter:on
verify(authenticationConverter).convert(any());
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof OAuth2TokenIntrospectionAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(tokenIntrospectionAuthentication));
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof OAuth2TokenIntrospectionAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(tokenIntrospectionAuthentication));
}
@@ -486,7 +511,9 @@ public class OAuth2TokenIntrospectionTests {
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint ->
tokenIntrospectionEndpoint
.introspectionRequestConverter(authenticationConverter)
.introspectionRequestConverters(authenticationConvertersConsumer)
.authenticationProvider(authenticationProvider)
.authenticationProviders(authenticationProvidersConsumer)
.introspectionResponseHandler(authenticationSuccessHandler)
.errorResponseHandler(authenticationFailureHandler));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

View File

@@ -18,6 +18,8 @@ package org.springframework.security.oauth2.server.authorization.config.annotati
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.function.Consumer;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
@@ -27,6 +29,7 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -56,6 +59,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
@@ -65,6 +69,7 @@ import org.springframework.security.oauth2.server.authorization.client.TestRegis
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.test.SpringTestRule;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
@@ -93,7 +98,9 @@ public class OAuth2TokenRevocationTests {
private static EmbeddedDatabase db;
private static JWKSource<SecurityContext> jwkSource;
private static AuthenticationConverter authenticationConverter;
private static Consumer<List<AuthenticationConverter>> authenticationConvertersConsumer;
private static AuthenticationProvider authenticationProvider;
private static Consumer<List<AuthenticationProvider>> authenticationProvidersConsumer;
private static AuthenticationSuccessHandler authenticationSuccessHandler;
private static AuthenticationFailureHandler authenticationFailureHandler;
@@ -117,7 +124,9 @@ public class OAuth2TokenRevocationTests {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
authenticationConverter = mock(AuthenticationConverter.class);
authenticationConvertersConsumer = mock(Consumer.class);
authenticationProvider = mock(AuthenticationProvider.class);
authenticationProvidersConsumer = mock(Consumer.class);
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
db = new EmbeddedDatabaseBuilder()
@@ -218,7 +227,25 @@ public class OAuth2TokenRevocationTests {
.andExpect(status().isOk());
verify(authenticationConverter).convert(any());
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationConverter>> authenticationConvertersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture());
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
assertThat(authenticationConverters).allMatch((converter) ->
converter == authenticationConverter ||
converter instanceof OAuth2TokenRevocationAuthenticationConverter);
verify(authenticationProvider).authenticate(eq(tokenRevocationAuthentication));
@SuppressWarnings("unchecked")
ArgumentCaptor<List<AuthenticationProvider>> authenticationProvidersCaptor = ArgumentCaptor.forClass(List.class);
verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture());
List<AuthenticationProvider> authenticationProviders = authenticationProvidersCaptor.getValue();
assertThat(authenticationProviders).allMatch((provider) ->
provider == authenticationProvider ||
provider instanceof OAuth2TokenRevocationAuthenticationProvider);
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(tokenRevocationAuthentication));
}
@@ -304,7 +331,9 @@ public class OAuth2TokenRevocationTests {
.tokenRevocationEndpoint(tokenRevocationEndpoint ->
tokenRevocationEndpoint
.revocationRequestConverter(authenticationConverter)
.revocationRequestConverters(authenticationConvertersConsumer)
.authenticationProvider(authenticationProvider)
.authenticationProviders(authenticationProvidersConsumer)
.revocationResponseHandler(authenticationSuccessHandler)
.errorResponseHandler(authenticationFailureHandler));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

View File

@@ -24,6 +24,7 @@ import java.util.Base64;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
@@ -70,6 +71,7 @@ import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadataClaimNames;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
@@ -80,6 +82,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.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
import org.springframework.security.oauth2.server.authorization.oidc.OidcProviderConfiguration;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.test.SpringTestRule;
import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
@@ -102,6 +105,7 @@ import org.springframework.web.util.UriComponentsBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -197,6 +201,17 @@ public class OidcTests {
.andExpect(status().is2xxSuccessful());
}
// gh-616
@Test
public void requestWhenConfigurationRequestAndConfigurationCustomizerSetThenReturnCustomConfigurationResponse() throws Exception {
this.spring.register(AuthorizationServerConfigurationWithProviderConfigurationCustomizer.class).autowire();
this.mvc.perform(get(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED,
hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL)));
}
@Test
public void loadContextWhenIssuerNotValidUrlThenThrowException() {
assertThatThrownBy(
@@ -466,6 +481,43 @@ public class OidcTests {
}
@Configuration
@EnableWebSecurity
static class AuthorizationServerConfigurationWithProviderConfigurationCustomizer extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.oidc(oidc ->
oidc.providerConfigurationEndpoint(providerConfigurationEndpoint ->
providerConfigurationEndpoint
.providerConfigurationCustomizer(providerConfigurationCustomizer())));
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
http
.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher));
return http.build();
}
// @formatter:on
private Consumer<OidcProviderConfiguration.Builder> providerConfigurationCustomizer() {
return (providerConfiguration) ->
providerConfiguration.scope(OidcScopes.PROFILE).scope(OidcScopes.EMAIL);
}
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfigurationWithIssuer extends AuthorizationServerConfiguration {

View File

@@ -31,6 +31,7 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -40,9 +41,11 @@ import static org.mockito.Mockito.verifyNoInteractions;
* Tests for {@link OidcProviderConfigurationEndpointFilter}.
*
* @author Daniel Garnier-Moiroux
* @author Joe Grandja
*/
public class OidcProviderConfigurationEndpointFilterTests {
private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
private final OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
@After
public void cleanup() {
@@ -50,35 +53,34 @@ public class OidcProviderConfigurationEndpointFilterTests {
}
@Test
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
public void setProviderConfigurationCustomizerWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.filter.setProviderConfigurationCustomizer(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("providerConfigurationCustomizer cannot be null");
}
@Test
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
request.setServletPath(requestUri);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@Test
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
request.setServletPath(requestUri);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@@ -103,7 +105,6 @@ public class OidcProviderConfigurationEndpointFilterTests {
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint)
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -111,7 +112,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verifyNoInteractions(filterChain);
@@ -140,7 +141,6 @@ public class OidcProviderConfigurationEndpointFilterTests {
.issuer("https://this is an invalid URL")
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter();
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -149,7 +149,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
FilterChain filterChain = mock(FilterChain.class);
assertThatIllegalArgumentException()
.isThrownBy(() -> filter.doFilter(request, response, filterChain))
.isThrownBy(() -> this.filter.doFilter(request, response, filterChain))
.withMessage("issuer must be a valid URL");
}

View File

@@ -152,7 +152,10 @@ public class JwtGeneratorTests {
@Test
public void generateWhenIdTokenTypeThenReturnJwt() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build();
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.scope(OidcScopes.OPENID)
.tokenSettings(TokenSettings.builder().idTokenSignatureAlgorithm(SignatureAlgorithm.ES256).build())
.build();
Map<String, Object> authenticationRequestAdditionalParameters = new HashMap<>();
authenticationRequestAdditionalParameters.put(OidcParameterNames.NONCE, "nonce");
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(
@@ -202,7 +205,11 @@ public class JwtGeneratorTests {
verify(this.jwtEncoder).encode(jwtEncoderParametersCaptor.capture());
JwsHeader jwsHeader = jwtEncoderParametersCaptor.getValue().getJwsHeader();
assertThat(jwsHeader.getAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
if (OidcParameterNames.ID_TOKEN.equals(tokenContext.getTokenType().getValue())) {
assertThat(jwsHeader.getAlgorithm()).isEqualTo(tokenContext.getRegisteredClient().getTokenSettings().getIdTokenSignatureAlgorithm());
} else {
assertThat(jwsHeader.getAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
}
JwtClaimsSet jwtClaimsSet = jwtEncoderParametersCaptor.getValue().getClaims();
assertThat(jwtClaimsSet.getIssuer().toExternalForm()).isEqualTo(tokenContext.getAuthorizationServerContext().getIssuer());

View File

@@ -31,6 +31,7 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -40,9 +41,11 @@ import static org.mockito.Mockito.verifyNoInteractions;
* Tests for {@link OAuth2AuthorizationServerMetadataEndpointFilter}.
*
* @author Daniel Garnier-Moiroux
* @author Joe Grandja
*/
public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
private static final String DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI = "/.well-known/oauth-authorization-server";
private final OAuth2AuthorizationServerMetadataEndpointFilter filter = new OAuth2AuthorizationServerMetadataEndpointFilter();
@After
public void cleanup() {
@@ -50,39 +53,34 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
}
@Test
public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
.issuer("https://example.com")
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OAuth2AuthorizationServerMetadataEndpointFilter filter = new OAuth2AuthorizationServerMetadataEndpointFilter();
public void setAuthorizationServerMetadataCustomizerWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> this.filter.setAuthorizationServerMetadataCustomizer(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("authorizationServerMetadataCustomizer cannot be null");
}
@Test
public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception {
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
request.setServletPath(requestUri);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@Test
public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception {
AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder()
.issuer("https://example.com")
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OAuth2AuthorizationServerMetadataEndpointFilter filter = new OAuth2AuthorizationServerMetadataEndpointFilter();
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
request.setServletPath(requestUri);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@@ -105,7 +103,6 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint)
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OAuth2AuthorizationServerMetadataEndpointFilter filter = new OAuth2AuthorizationServerMetadataEndpointFilter();
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -113,7 +110,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
filter.doFilter(request, response, filterChain);
this.filter.doFilter(request, response, filterChain);
verifyNoInteractions(filterChain);
@@ -139,7 +136,6 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
.issuer("https://this is an invalid URL")
.build();
AuthorizationServerContextHolder.setContext(new TestAuthorizationServerContext(authorizationServerSettings, null));
OAuth2AuthorizationServerMetadataEndpointFilter filter = new OAuth2AuthorizationServerMetadataEndpointFilter();
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -149,7 +145,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
assertThatIllegalArgumentException()
.isThrownBy(() -> filter.doFilter(request, response, filterChain))
.isThrownBy(() -> this.filter.doFilter(request, response, filterChain))
.withMessage("issuer must be a valid URL");
}