From c2d79fcbd6f06eba8c835a7cfb5f413d41136d8b Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Wed, 3 Aug 2022 17:30:19 -0600 Subject: [PATCH] Add Conditions to Generating AuthnRequest Closes gh-11657 --- .../saml2/Saml2LoginConfigurer.java | 25 +++++++++++++++++-- .../saml2/Saml2LoginConfigurerTests.java | 11 ++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java index 578c1d295e..10952228d5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java @@ -47,10 +47,16 @@ import org.springframework.security.saml2.provider.service.web.Saml2Authenticati import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository; import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter; import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; +import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationConverter; +import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter; +import org.springframework.security.web.util.matcher.AndRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.security.web.util.matcher.OrRequestMatcher; +import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -252,8 +258,7 @@ public final class Saml2LoginConfigurer> this.updateAuthenticationDefaults(); this.updateAccessDefaults(http); String loginUrl = providerUrlMap.entrySet().iterator().next().getKey(); - final LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(loginUrl); - registerAuthenticationEntryPoint(http, entryPoint); + registerAuthenticationEntryPoint(http, getLoginEntryPoint(http, loginUrl)); } else { super.init(http); @@ -295,6 +300,22 @@ public final class Saml2LoginConfigurer> return this.relyingPartyRegistrationRepository; } + private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) { + RequestMatcher loginPageMatcher = new AntPathRequestMatcher(this.getLoginPage()); + RequestMatcher faviconMatcher = new AntPathRequestMatcher("/favicon.ico"); + RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http); + RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher( + new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); + RequestMatcher notXRequestedWith = new NegatedRequestMatcher( + new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); + LinkedHashMap entryPoints = new LinkedHashMap<>(); + entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)), + new LoginUrlAuthenticationEntryPoint(providerLoginPage)); + DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); + loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint()); + return loginEntryPoint; + } + private void setAuthenticationRequestRepository(B http, Saml2WebSsoAuthenticationFilter saml2WebSsoAuthenticationFilter) { saml2WebSsoAuthenticationFilter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http)); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java index 0385408bc2..f160ec2d05 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java @@ -43,6 +43,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.core.convert.converter.Converter; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -412,6 +413,16 @@ public class Saml2LoginConfigurerTests { verify(authenticationConverter).convert(any(HttpServletRequest.class)); } + // gh-11657 + @Test + public void getFaviconWhenDefaultConfigurationThenDoesNotSaveAuthnRequest() throws Exception { + this.spring.register(Saml2LoginConfig.class).autowire(); + this.mvc.perform(get("/favicon.ico").accept(MediaType.TEXT_HTML)).andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/").accept(MediaType.TEXT_HTML)).andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/saml2/authenticate/registration-id")); + } + private void validateSaml2WebSsoAuthenticationFilterConfiguration() { // get the OpenSamlAuthenticationProvider Saml2WebSsoAuthenticationFilter filter = getSaml2SsoFilter(this.springSecurityFilterChain);