Skip to content

Commit fcd8a38

Browse files
Daniel Meierjgrandja
authored andcommitted
Add success handler modification of OAuth2LoginSpec
Add the ability to modify the success handler used in OAuth2LoginSpec. The default success handler remains unchanged. Closes #6863
1 parent 8716a3e commit fcd8a38

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ public class OAuth2LoginSpec {
695695

696696
private ServerWebExchangeMatcher authenticationMatcher;
697697

698+
private ServerAuthenticationSuccessHandler authenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler();
699+
698700
/**
699701
* Configures the {@link ReactiveAuthenticationManager} to use. The default is
700702
* {@link OAuth2AuthorizationCodeReactiveAuthenticationManager}
@@ -706,6 +708,20 @@ public OAuth2LoginSpec authenticationManager(ReactiveAuthenticationManager authe
706708
return this;
707709
}
708710

711+
/**
712+
* The {@link ServerAuthenticationSuccessHandler} used after authentication success. Defaults to
713+
* {@link RedirectServerAuthenticationSuccessHandler} redirecting to "/".
714+
*
715+
* @since 5.2
716+
* @param authenticationSuccessHandler the success handler to use
717+
* @return the {@link OAuth2LoginSpec} to customize
718+
*/
719+
public OAuth2LoginSpec authenticationSuccessHandler(ServerAuthenticationSuccessHandler authenticationSuccessHandler) {
720+
Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
721+
this.authenticationSuccessHandler = authenticationSuccessHandler;
722+
return this;
723+
}
724+
709725
/**
710726
* Gets the {@link ReactiveAuthenticationManager} to use. First tries an explicitly configured manager, and
711727
* defaults to {@link OAuth2AuthorizationCodeReactiveAuthenticationManager}
@@ -821,9 +837,8 @@ protected void configure(ServerHttpSecurity http) {
821837
AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, authorizedClientRepository);
822838
authenticationFilter.setRequiresAuthenticationMatcher(getAuthenticationMatcher());
823839
authenticationFilter.setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository));
824-
RedirectServerAuthenticationSuccessHandler redirectHandler = new RedirectServerAuthenticationSuccessHandler();
825840

826-
authenticationFilter.setAuthenticationSuccessHandler(redirectHandler);
841+
authenticationFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
827842
authenticationFilter.setAuthenticationFailureHandler(new ServerAuthenticationFailureHandler() {
828843
@Override
829844
public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange,

config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323

2424
import org.junit.Rule;
2525
import org.junit.Test;
26+
import org.mockito.stubbing.Answer;
2627
import org.openqa.selenium.WebDriver;
28+
import org.springframework.security.web.server.WebFilterExchange;
29+
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
30+
import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
2731
import reactor.core.publisher.Mono;
2832

2933
import org.springframework.beans.factory.annotation.Autowired;
@@ -184,6 +188,8 @@ public void oauth2LoginWhenCustomObjectsThenUsed() {
184188
this.spring.register(OAuth2LoginWithSingleClientRegistrations.class,
185189
OAuth2LoginMockAuthenticationManagerConfig.class).autowire();
186190

191+
String redirectLocation = "/custom-redirect-location";
192+
187193
WebTestClient webTestClient = WebTestClientBuilder
188194
.bindToWebFilters(this.springSecurity)
189195
.build();
@@ -194,6 +200,7 @@ public void oauth2LoginWhenCustomObjectsThenUsed() {
194200
ReactiveAuthenticationManager manager = config.manager;
195201
ServerWebExchangeMatcher matcher = config.matcher;
196202
ServerOAuth2AuthorizationRequestResolver resolver = config.resolver;
203+
ServerAuthenticationSuccessHandler successHandler = config.successHandler;
197204

198205
OAuth2AuthorizationExchange exchange = TestOAuth2AuthorizationExchanges.success();
199206
OAuth2User user = TestOAuth2Users.create();
@@ -205,16 +212,25 @@ public void oauth2LoginWhenCustomObjectsThenUsed() {
205212
when(manager.authenticate(any())).thenReturn(Mono.just(result));
206213
when(matcher.matches(any())).thenReturn(ServerWebExchangeMatcher.MatchResult.match());
207214
when(resolver.resolve(any())).thenReturn(Mono.empty());
215+
when(successHandler.onAuthenticationSuccess(any(), any())).thenAnswer((Answer<Mono<Void>>) invocation -> {
216+
WebFilterExchange webFilterExchange = invocation.getArgument(0);
217+
Authentication authentication = invocation.getArgument(1);
218+
219+
return new RedirectServerAuthenticationSuccessHandler(redirectLocation)
220+
.onAuthenticationSuccess(webFilterExchange, authentication);
221+
});
208222

209223
webTestClient.get()
210224
.uri("/login/oauth2/code/github")
211225
.exchange()
212-
.expectStatus().is3xxRedirection();
226+
.expectStatus().is3xxRedirection()
227+
.expectHeader().valueEquals("Location", redirectLocation);
213228

214229
verify(converter).convert(any());
215230
verify(manager).authenticate(any());
216231
verify(matcher).matches(any());
217232
verify(resolver).resolve(any());
233+
verify(successHandler).onAuthenticationSuccess(any(), any());
218234
}
219235

220236
@Configuration
@@ -227,6 +243,8 @@ static class OAuth2LoginMockAuthenticationManagerConfig {
227243

228244
ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
229245

246+
ServerAuthenticationSuccessHandler successHandler = mock(ServerAuthenticationSuccessHandler.class);
247+
230248
@Bean
231249
public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
232250
http
@@ -237,7 +255,8 @@ public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
237255
.authenticationConverter(authenticationConverter)
238256
.authenticationManager(manager)
239257
.authenticationMatcher(matcher)
240-
.authorizationRequestResolver(resolver);
258+
.authorizationRequestResolver(resolver)
259+
.authenticationSuccessHandler(successHandler);
241260
return http.build();
242261
}
243262
}
@@ -425,4 +444,5 @@ Mono<SecurityContext> authentication(Authentication authentication) {
425444
<T> T getBean(Class<T> beanClass) {
426445
return this.spring.getContext().getBean(beanClass);
427446
}
447+
428448
}

0 commit comments

Comments
 (0)