Skip to content

Commit fe71744

Browse files
committed
Add authenticationFailureHandlerSetter in Oauth2LoginConfigurer and change InvalidClientRegistrationIdException from package-private to public
1 parent e3de24a commit fe71744

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

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

+21
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import org.springframework.security.oauth2.jwt.JwtDecoderFactory;
8383
import org.springframework.security.web.AuthenticationEntryPoint;
8484
import org.springframework.security.web.RedirectStrategy;
85+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
8586
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
8687
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
8788
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
@@ -417,6 +418,10 @@ public void configure(B http) throws Exception {
417418
authorizationRequestFilter
418419
.setAuthorizationRedirectStrategy(this.authorizationEndpointConfig.authorizationRedirectStrategy);
419420
}
421+
if (this.authorizationEndpointConfig.authenticationFailureHandler != null) {
422+
authorizationRequestFilter
423+
.setAuthenticationFailureHandler(this.authorizationEndpointConfig.authenticationFailureHandler);
424+
}
420425
RequestCache requestCache = http.getSharedObject(RequestCache.class);
421426
if (requestCache != null) {
422427
authorizationRequestFilter.setRequestCache(requestCache);
@@ -617,6 +622,8 @@ public final class AuthorizationEndpointConfig {
617622

618623
private RedirectStrategy authorizationRedirectStrategy;
619624

625+
private AuthenticationFailureHandler authenticationFailureHandler;
626+
620627
private AuthorizationEndpointConfig() {
621628
}
622629

@@ -670,6 +677,20 @@ public AuthorizationEndpointConfig authorizationRedirectStrategy(
670677
return this;
671678
}
672679

680+
/**
681+
* Sets the {@link AuthenticationFailureHandler} used to handle errors redirecting
682+
* to the Authorization Server's Authorization Endpoint.
683+
* @param authenticationFailureHandler the {@link AuthenticationFailureHandler}
684+
* used to handle errors redirecting to the Authorization Server's Authorization
685+
* Endpoint
686+
* @since 6.3
687+
*/
688+
public AuthorizationEndpointConfig authenticationFailureHandler(
689+
AuthenticationFailureHandler authenticationFailureHandler) {
690+
this.authenticationFailureHandler = authenticationFailureHandler;
691+
return this;
692+
}
693+
673694
/**
674695
* Returns the {@link OAuth2LoginConfigurer} for further configuration.
675696
* @return the {@link OAuth2LoginConfigurer}

config/src/main/kotlin/org/springframework/security/config/annotation/web/oauth2/login/AuthorizationEndpointDsl.kt

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.springframework.security.oauth2.client.web.AuthorizationRequestReposi
2222
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver
2323
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
2424
import org.springframework.security.web.RedirectStrategy
25+
import org.springframework.security.web.authentication.AuthenticationFailureHandler
2526

2627
/**
2728
* A Kotlin DSL to configure the Authorization Server's Authorization Endpoint using
@@ -40,13 +41,15 @@ class AuthorizationEndpointDsl {
4041
var authorizationRequestResolver: OAuth2AuthorizationRequestResolver? = null
4142
var authorizationRequestRepository: AuthorizationRequestRepository<OAuth2AuthorizationRequest>? = null
4243
var authorizationRedirectStrategy: RedirectStrategy? = null
44+
var authenticationFailureHandler: AuthenticationFailureHandler? = null
4345

4446
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.AuthorizationEndpointConfig) -> Unit {
4547
return { authorizationEndpoint ->
4648
baseUri?.also { authorizationEndpoint.baseUri(baseUri) }
4749
authorizationRequestResolver?.also { authorizationEndpoint.authorizationRequestResolver(authorizationRequestResolver) }
4850
authorizationRequestRepository?.also { authorizationEndpoint.authorizationRequestRepository(authorizationRequestRepository) }
4951
authorizationRedirectStrategy?.also { authorizationEndpoint.authorizationRedirectStrategy(authorizationRedirectStrategy) }
52+
authenticationFailureHandler?.also { authorizationEndpoint.authenticationFailureHandler(authenticationFailureHandler) }
5053
}
5154
}
5255
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java

+44
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.junit.jupiter.api.BeforeEach;
2929
import org.junit.jupiter.api.Test;
3030
import org.junit.jupiter.api.extension.ExtendWith;
31+
import org.mockito.ArgumentCaptor;
3132

3233
import org.springframework.beans.factory.BeanCreationException;
3334
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
@@ -49,6 +50,7 @@
4950
import org.springframework.security.config.test.SpringTestContext;
5051
import org.springframework.security.config.test.SpringTestContextExtension;
5152
import org.springframework.security.core.Authentication;
53+
import org.springframework.security.core.AuthenticationException;
5254
import org.springframework.security.core.GrantedAuthority;
5355
import org.springframework.security.core.authority.AuthorityUtils;
5456
import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -68,6 +70,7 @@
6870
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
6971
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
7072
import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository;
73+
import org.springframework.security.oauth2.client.web.InvalidClientRegistrationIdException;
7174
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
7275
import org.springframework.security.oauth2.core.OAuth2AccessToken;
7376
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
@@ -91,6 +94,7 @@
9194
import org.springframework.security.web.FilterChainProxy;
9295
import org.springframework.security.web.RedirectStrategy;
9396
import org.springframework.security.web.SecurityFilterChain;
97+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
9498
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
9599
import org.springframework.security.web.context.HttpRequestResponseHolder;
96100
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@@ -537,6 +541,23 @@ public void requestWhenOauth2LoginWithCustomLoginPageInLambdaThenRedirectCustomL
537541
assertThat(this.response.getRedirectedUrl()).matches("http://localhost/custom-login");
538542
}
539543

544+
// gh-13793
545+
@Test
546+
public void oauth2LoginWithCustomAuthenticationFailureHandlerThenUsedWithInvalidClientRegistrationIdException()
547+
throws Exception {
548+
loadConfig(OAuth2LoginConfigCustomAuthenticationFailureHandler.class);
549+
AuthenticationFailureHandler authenticationFailureHandler = this.context
550+
.getBean(OAuth2LoginConfigCustomAuthenticationFailureHandler.class).authenticationFailureHandler;
551+
String requestUri = "/oauth2/authorization/invalid-client-registration-id";
552+
this.request = new MockHttpServletRequest("GET", requestUri);
553+
this.request.setServletPath(requestUri);
554+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
555+
556+
ArgumentCaptor<AuthenticationException> capture = ArgumentCaptor.forClass(AuthenticationException.class);
557+
then(authenticationFailureHandler).should().onAuthenticationFailure(any(), any(), capture.capture());
558+
assertThat(capture.getValue()).hasCauseInstanceOf(InvalidClientRegistrationIdException.class);
559+
}
560+
540561
@Test
541562
public void oidcLogin() throws Exception {
542563
// setup application context
@@ -1069,6 +1090,29 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
10691090

10701091
}
10711092

1093+
@Configuration
1094+
@EnableWebSecurity
1095+
static class OAuth2LoginConfigCustomAuthenticationFailureHandler extends CommonSecurityFilterChainConfig {
1096+
1097+
AuthenticationFailureHandler authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
1098+
1099+
@Bean
1100+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
1101+
// @formatter:off
1102+
http
1103+
.oauth2Login()
1104+
.clientRegistrationRepository(
1105+
new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION))
1106+
.authorizationEndpoint((authorizationEndpoint) ->
1107+
authorizationEndpoint
1108+
.authenticationFailureHandler(this.authenticationFailureHandler)
1109+
);
1110+
// @formatter:on
1111+
return super.configureFilterChain(http);
1112+
}
1113+
1114+
}
1115+
10721116
@Configuration
10731117
@EnableWebSecurity
10741118
static class OAuth2LoginConfigWithOidcLogoutSuccessHandler extends CommonSecurityFilterChainConfig {

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/InvalidClientRegistrationIdException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* @author Steve Riesenberg
2121
* @since 5.8
2222
*/
23-
class InvalidClientRegistrationIdException extends IllegalArgumentException {
23+
public class InvalidClientRegistrationIdException extends IllegalArgumentException {
2424

2525
/**
2626
* @param message the exception message

0 commit comments

Comments
 (0)