Skip to content

Commit 5bb5d0f

Browse files
committed
Polish gh-16589
1 parent fc1469a commit 5bb5d0f

File tree

16 files changed

+1580
-503
lines changed

16 files changed

+1580
-503
lines changed

Diff for: config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,9 +34,8 @@
3434
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3535
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3636
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
37-
import org.springframework.context.ApplicationContext;
38-
import org.springframework.context.ApplicationContextAware;
3937
import org.springframework.context.ApplicationEventPublisher;
38+
import org.springframework.context.ApplicationEventPublisherAware;
4039
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
4140
import org.springframework.context.annotation.Bean;
4241
import org.springframework.context.annotation.Configuration;
@@ -163,7 +162,7 @@ private OAuth2AuthorizedClientManager getAuthorizedClientManager() {
163162
* @since 6.2.0
164163
*/
165164
static final class OAuth2AuthorizedClientManagerRegistrar
166-
implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor, BeanFactoryAware {
165+
implements ApplicationEventPublisherAware, BeanDefinitionRegistryPostProcessor, BeanFactoryAware {
167166

168167
static final String BEAN_NAME = "authorizedClientManagerRegistrar";
169168

@@ -182,7 +181,7 @@ static final class OAuth2AuthorizedClientManagerRegistrar
182181

183182
private final AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
184183

185-
private ApplicationEventPublisher eventPublisher;
184+
private ApplicationEventPublisher applicationEventPublisher;
186185

187186
private ListableBeanFactory beanFactory;
188187

@@ -307,8 +306,8 @@ private OAuth2AuthorizedClientProvider getRefreshTokenAuthorizedClientProvider(
307306
authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
308307
}
309308

310-
if (this.eventPublisher != null) {
311-
authorizedClientProvider.setApplicationEventPublisher(this.eventPublisher);
309+
if (this.applicationEventPublisher != null) {
310+
authorizedClientProvider.setApplicationEventPublisher(this.applicationEventPublisher);
312311
}
313312

314313
return authorizedClientProvider;
@@ -433,8 +432,8 @@ private <T> T getBeanOfType(ResolvableType resolvableType) {
433432
}
434433

435434
@Override
436-
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
437-
this.eventPublisher = applicationContext;
435+
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
436+
this.applicationEventPublisher = applicationEventPublisher;
438437
}
439438

440439
}

Diff for: config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

+24-10
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
5858
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
5959
import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider;
60-
import org.springframework.security.oauth2.client.oidc.authentication.RefreshOidcIdTokenHandler;
60+
import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizedClientRefreshedEventListener;
6161
import org.springframework.security.oauth2.client.oidc.session.InMemoryOidcSessionRegistry;
6262
import org.springframework.security.oauth2.client.oidc.session.OidcSessionInformation;
6363
import org.springframework.security.oauth2.client.oidc.session.OidcSessionRegistry;
@@ -91,6 +91,7 @@
9191
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
9292
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
9393
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
94+
import org.springframework.security.web.context.SecurityContextRepository;
9495
import org.springframework.security.web.csrf.CsrfToken;
9596
import org.springframework.security.web.savedrequest.RequestCache;
9697
import org.springframework.security.web.util.matcher.AndRequestMatcher;
@@ -387,23 +388,26 @@ public void init(B http) throws Exception {
387388
OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService = getOidcUserService();
388389
OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider(
389390
accessTokenResponseClient, oidcUserService);
391+
OidcAuthorizedClientRefreshedEventListener oidcAuthorizedClientRefreshedEventListener = new OidcAuthorizedClientRefreshedEventListener();
392+
oidcAuthorizedClientRefreshedEventListener.setUserService(oidcUserService);
393+
oidcAuthorizedClientRefreshedEventListener
394+
.setApplicationEventPublisher(http.getSharedObject(ApplicationContext.class));
395+
390396
JwtDecoderFactory<ClientRegistration> jwtDecoderFactory = this.getJwtDecoderFactoryBean();
391397
if (jwtDecoderFactory != null) {
392398
oidcAuthorizationCodeAuthenticationProvider.setJwtDecoderFactory(jwtDecoderFactory);
399+
oidcAuthorizedClientRefreshedEventListener.setJwtDecoderFactory(jwtDecoderFactory);
393400
}
394401
if (userAuthoritiesMapper != null) {
395402
oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper);
403+
oidcAuthorizedClientRefreshedEventListener.setAuthoritiesMapper(userAuthoritiesMapper);
396404
}
397-
http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
405+
oidcAuthorizationCodeAuthenticationProvider = this.postProcess(oidcAuthorizationCodeAuthenticationProvider);
406+
http.authenticationProvider(oidcAuthorizationCodeAuthenticationProvider);
398407

399-
RefreshOidcIdTokenHandler refreshOidcIdTokenHandler = new RefreshOidcIdTokenHandler();
400-
if (this.getSecurityContextHolderStrategy() != null) {
401-
refreshOidcIdTokenHandler.setSecurityContextHolderStrategy(this.getSecurityContextHolderStrategy());
402-
}
403-
if (jwtDecoderFactory != null) {
404-
refreshOidcIdTokenHandler.setJwtDecoderFactory(jwtDecoderFactory);
405-
}
406-
registerDelegateApplicationListener(refreshOidcIdTokenHandler);
408+
oidcAuthorizedClientRefreshedEventListener = this.postProcess(oidcAuthorizedClientRefreshedEventListener);
409+
registerDelegateApplicationListener(oidcAuthorizedClientRefreshedEventListener);
410+
configureOidcUserRefreshedEventListener(http);
407411
}
408412
else {
409413
http.authenticationProvider(new OidcAuthenticationRequestChecker());
@@ -631,6 +635,16 @@ private void configureOidcSessionRegistry(B http) {
631635
registerDelegateApplicationListener(listener);
632636
}
633637

638+
private void configureOidcUserRefreshedEventListener(B http) {
639+
OidcUserRefreshedEventListener oidcUserRefreshedEventListener = new OidcUserRefreshedEventListener();
640+
oidcUserRefreshedEventListener.setSecurityContextHolderStrategy(this.getSecurityContextHolderStrategy());
641+
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
642+
if (securityContextRepository != null) {
643+
oidcUserRefreshedEventListener.setSecurityContextRepository(securityContextRepository);
644+
}
645+
registerDelegateApplicationListener(oidcUserRefreshedEventListener);
646+
}
647+
634648
private void registerDelegateApplicationListener(ApplicationListener<?> delegate) {
635649
DelegatingApplicationListener delegating = getBeanOrNull(
636650
ResolvableType.forType(DelegatingApplicationListener.class));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
18+
19+
import jakarta.servlet.http.HttpServletRequest;
20+
import jakarta.servlet.http.HttpServletResponse;
21+
22+
import org.springframework.context.ApplicationListener;
23+
import org.springframework.security.core.context.SecurityContext;
24+
import org.springframework.security.core.context.SecurityContextHolder;
25+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
26+
import org.springframework.security.oauth2.client.oidc.authentication.event.OidcUserRefreshedEvent;
27+
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
28+
import org.springframework.security.web.context.SecurityContextRepository;
29+
import org.springframework.util.Assert;
30+
import org.springframework.web.context.request.RequestAttributes;
31+
import org.springframework.web.context.request.RequestContextHolder;
32+
import org.springframework.web.context.request.ServletRequestAttributes;
33+
34+
/**
35+
* An {@link ApplicationListener} that listens for events of type
36+
* {@link OidcUserRefreshedEvent} and refreshes the {@link SecurityContext}.
37+
*
38+
* @author Steve Riesenberg
39+
* @since 6.5
40+
* @see org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider
41+
*/
42+
final class OidcUserRefreshedEventListener implements ApplicationListener<OidcUserRefreshedEvent> {
43+
44+
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
45+
.getContextHolderStrategy();
46+
47+
private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
48+
49+
@Override
50+
public void onApplicationEvent(OidcUserRefreshedEvent event) {
51+
SecurityContext securityContext = this.securityContextHolderStrategy.createEmptyContext();
52+
securityContext.setAuthentication(event.getAuthentication());
53+
this.securityContextHolderStrategy.setContext(securityContext);
54+
55+
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
56+
if (!(requestAttributes instanceof ServletRequestAttributes servletRequestAttributes)) {
57+
return;
58+
}
59+
60+
HttpServletRequest request = servletRequestAttributes.getRequest();
61+
HttpServletResponse response = servletRequestAttributes.getResponse();
62+
this.securityContextRepository.saveContext(securityContext, request, response);
63+
}
64+
65+
/**
66+
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
67+
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
68+
* @param securityContextHolderStrategy the {@link SecurityContextHolderStrategy} to
69+
* use
70+
*/
71+
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
72+
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
73+
this.securityContextHolderStrategy = securityContextHolderStrategy;
74+
}
75+
76+
/**
77+
* Sets the {@link SecurityContextRepository} to save the {@link SecurityContext} upon
78+
* receiving an {@link OidcUserRefreshedEvent}.
79+
* @param securityContextRepository the {@link SecurityContextRepository} to use
80+
*/
81+
void setSecurityContextRepository(SecurityContextRepository securityContextRepository) {
82+
Assert.notNull(securityContextRepository, "securityContextRepository cannot be null");
83+
this.securityContextRepository = securityContextRepository;
84+
}
85+
86+
}

Diff for: config/src/main/java/org/springframework/security/config/http/OAuth2AuthorizedClientManagerRegistrar.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)