@ -29,6 +29,7 @@ import org.junit.jupiter.api.AfterEach;
@@ -29,6 +29,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach ;
import org.junit.jupiter.api.Test ;
import org.junit.jupiter.api.extension.ExtendWith ;
import org.mockito.Mockito ;
import org.springframework.beans.factory.BeanCreationException ;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException ;
@ -43,11 +44,14 @@ import org.springframework.http.MediaType;
@@ -43,11 +44,14 @@ import org.springframework.http.MediaType;
import org.springframework.mock.web.MockFilterChain ;
import org.springframework.mock.web.MockHttpServletRequest ;
import org.springframework.mock.web.MockHttpServletResponse ;
import org.springframework.security.authentication.AuthenticationProvider ;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent ;
import org.springframework.security.config.Customizer ;
import org.springframework.security.config.ObjectPostProcessor ;
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig ;
import org.springframework.security.config.annotation.web.builders.HttpSecurity ;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity ;
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurerTests.OAuth2LoginConfigCustomWithPostProcessor.SpyObjectPostProcessor ;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider ;
import org.springframework.security.config.test.SpringTestContext ;
import org.springframework.security.config.test.SpringTestContextExtension ;
@ -711,6 +715,22 @@ public class OAuth2LoginConfigurerTests {
@@ -711,6 +715,22 @@ public class OAuth2LoginConfigurerTests {
verifyNoInteractions ( clientRegistrationRepository , authorizedClientRepository ) ;
}
// gh-17175
@Test
public void oauth2LoginWhenAuthenticationProviderPostProcessorThenUses ( ) throws Exception {
loadConfig ( OAuth2LoginConfigCustomWithPostProcessor . class ) ;
// setup authorization request
OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest ( ) ;
this . authorizationRequestRepository . saveAuthorizationRequest ( authorizationRequest , this . request , this . response ) ;
// setup authentication parameters
this . request . setParameter ( "code" , "code123" ) ;
this . request . setParameter ( "state" , authorizationRequest . getState ( ) ) ;
// perform test
this . springSecurityFilterChain . doFilter ( this . request , this . response , this . filterChain ) ;
// assertions
verify ( this . context . getBean ( SpyObjectPostProcessor . class ) . spy ) . authenticate ( any ( ) ) ;
}
private void loadConfig ( Class < ? > . . . configs ) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext ( ) ;
applicationContext . register ( configs ) ;
@ -1296,6 +1316,52 @@ public class OAuth2LoginConfigurerTests {
@@ -1296,6 +1316,52 @@ public class OAuth2LoginConfigurerTests {
}
@Configuration
@EnableWebSecurity
static class OAuth2LoginConfigCustomWithPostProcessor {
private final ClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository (
GOOGLE_CLIENT_REGISTRATION ) ;
private final ObjectPostProcessor < AuthenticationProvider > postProcessor = new SpyObjectPostProcessor ( ) ;
@Bean
SecurityFilterChain filterChain ( HttpSecurity http ) throws Exception {
// @formatter:off
http
. oauth2Login ( ( oauth2Login ) - > oauth2Login
. clientRegistrationRepository ( this . clientRegistrationRepository )
. withObjectPostProcessor ( this . postProcessor )
) ;
// @formatter:on
return http . build ( ) ;
}
@Bean
ObjectPostProcessor < AuthenticationProvider > mockPostProcessor ( ) {
return this . postProcessor ;
}
@Bean
HttpSessionOAuth2AuthorizationRequestRepository oauth2AuthorizationRequestRepository ( ) {
return new HttpSessionOAuth2AuthorizationRequestRepository ( ) ;
}
static class SpyObjectPostProcessor implements ObjectPostProcessor < AuthenticationProvider > {
AuthenticationProvider spy ;
@Override
public < O extends AuthenticationProvider > O postProcess ( O object ) {
O spy = Mockito . spy ( object ) ;
this . spy = spy ;
return spy ;
}
}
}
private abstract static class CommonSecurityFilterChainConfig {
SecurityFilterChain configureFilterChain ( HttpSecurity http ) throws Exception {