|
43 | 43 | import org.springframework.mock.web.MockFilterChain;
|
44 | 44 | import org.springframework.mock.web.MockHttpServletRequest;
|
45 | 45 | import org.springframework.mock.web.MockHttpServletResponse;
|
| 46 | +import org.springframework.security.authentication.AuthenticationProvider; |
46 | 47 | import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
| 48 | +import org.springframework.security.config.ObjectPostProcessor; |
47 | 49 | import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
48 | 50 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
49 | 51 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
52 | 54 | import org.springframework.security.config.test.SpringTestContextExtension;
|
53 | 55 | import org.springframework.security.context.DelegatingApplicationListener;
|
54 | 56 | import org.springframework.security.core.Authentication;
|
| 57 | +import org.springframework.security.core.AuthenticationException; |
55 | 58 | import org.springframework.security.core.GrantedAuthority;
|
56 | 59 | import org.springframework.security.core.authority.AuthorityUtils;
|
57 | 60 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
@@ -214,6 +217,28 @@ public void oauth2Login() throws Exception {
|
214 | 217 | .hasToString("OAUTH2_USER");
|
215 | 218 | }
|
216 | 219 |
|
| 220 | + // gh-17175 |
| 221 | + @Test |
| 222 | + public void postProcessorSucceedsWhenProcessorReturnsAuthenticationProvider() throws Exception { |
| 223 | + loadConfig(OAuth2LoginConfigCustomWithPostProcessor.class); |
| 224 | + // setup authorization request |
| 225 | + OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); |
| 226 | + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); |
| 227 | + // setup authentication parameters |
| 228 | + this.request.setParameter("code", "code123"); |
| 229 | + this.request.setParameter("state", authorizationRequest.getState()); |
| 230 | + // perform test |
| 231 | + this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); |
| 232 | + // assertions |
| 233 | + Authentication authentication = this.securityContextRepository |
| 234 | + .loadContext(new HttpRequestResponseHolder(this.request, this.response)) |
| 235 | + .getAuthentication(); |
| 236 | + assertThat(authentication.getAuthorities()).hasSize(1); |
| 237 | + assertThat(authentication.getAuthorities()).first() |
| 238 | + .isInstanceOf(OAuth2UserAuthority.class) |
| 239 | + .hasToString("OAUTH2_USER"); |
| 240 | + } |
| 241 | + |
217 | 242 | @Test
|
218 | 243 | public void requestWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
|
219 | 244 | loadConfig(OAuth2LoginConfig.class, SecurityContextChangedListenerConfig.class);
|
@@ -1307,6 +1332,56 @@ OAuth2AuthorizedClientRepository authorizedClientRepository() {
|
1307 | 1332 |
|
1308 | 1333 | }
|
1309 | 1334 |
|
| 1335 | + @Configuration |
| 1336 | + @EnableWebSecurity |
| 1337 | + static class OAuth2LoginConfigCustomWithPostProcessor |
| 1338 | + extends CommonLambdaSecurityFilterChainConfig { |
| 1339 | + |
| 1340 | + private ClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository( |
| 1341 | + GOOGLE_CLIENT_REGISTRATION); |
| 1342 | + |
| 1343 | + OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); |
| 1344 | + |
| 1345 | + @Bean |
| 1346 | + SecurityFilterChain filterChain(HttpSecurity http) throws Exception { |
| 1347 | + // @formatter:off |
| 1348 | + http |
| 1349 | + .oauth2Login((oauth2Login) -> |
| 1350 | + oauth2Login |
| 1351 | + .clientRegistrationRepository(this.clientRegistrationRepository) |
| 1352 | +// .authorizedClientRepository(this.authorizedClientRepository) |
| 1353 | + .withObjectPostProcessor(new CustomProcessor()) |
| 1354 | + ); |
| 1355 | + // @formatter:on |
| 1356 | + return super.configureFilterChain(http); |
| 1357 | + } |
| 1358 | + |
| 1359 | + class CustomProcessor implements ObjectPostProcessor<AuthenticationProvider> { |
| 1360 | + @Override |
| 1361 | + public <O extends AuthenticationProvider> O postProcess(O object) { |
| 1362 | + AuthenticationProvider p = new NoopWrapperProvider(object); |
| 1363 | + |
| 1364 | + return (O) p; |
| 1365 | + } |
| 1366 | + } |
| 1367 | + |
| 1368 | + record NoopWrapperProvider( |
| 1369 | + AuthenticationProvider delegate |
| 1370 | + ) implements AuthenticationProvider { |
| 1371 | + |
| 1372 | + @Override |
| 1373 | + public Authentication authenticate(Authentication authentication) throws AuthenticationException { |
| 1374 | + return delegate.authenticate(authentication); |
| 1375 | + } |
| 1376 | + |
| 1377 | + @Override |
| 1378 | + public boolean supports(Class<?> authentication) { |
| 1379 | + return delegate.supports(authentication); |
| 1380 | + } |
| 1381 | + } |
| 1382 | + |
| 1383 | + } |
| 1384 | + |
1310 | 1385 | private abstract static class CommonSecurityFilterChainConfig {
|
1311 | 1386 |
|
1312 | 1387 | SecurityFilterChain configureFilterChain(HttpSecurity http) throws Exception {
|
|
0 commit comments