diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java index 8ce9b69bd2..43283b7ccf 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java @@ -51,6 +51,7 @@ import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; @@ -215,6 +216,8 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil public CasAuthenticationFilter() { super("/login/cas"); + RequestMatcher processUri = PathPatternRequestMatcher.withDefaults().matcher("/login/cas"); + setRequiresAuthenticationRequestMatcher(processUri); setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler()); setSecurityContextRepository(this.securityContextRepository); } @@ -319,6 +322,18 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler(failureHandler)); } + /** + * Use this {@code RequestMatcher} to match proxy receptor requests. Without setting + * this matcher, {@link CasAuthenticationFilter} will not capture any proxy receptor + * requets. + * @param proxyReceptorMatcher the {@link RequestMatcher} to use + * @since 6.5 + */ + public final void setProxyReceptorMatcher(RequestMatcher proxyReceptorMatcher) { + Assert.notNull(proxyReceptorMatcher, "proxyReceptorMatcher cannot be null"); + this.proxyReceptorMatcher = proxyReceptorMatcher; + } + public final void setProxyReceptorUrl(final String proxyReceptorUrl) { this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl); } diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java index 74a2e2ea13..296043527e 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java @@ -43,6 +43,7 @@ import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -267,4 +268,20 @@ public class CasAuthenticationFilterTests { verify(securityContextRepository).setContext(any(SecurityContext.class)); } + @Test + public void requiresAuthenticationWhenProxyRequestMatcherThenMatches() { + CasAuthenticationFilter filter = new CasAuthenticationFilter(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/pgtCallback"); + MockHttpServletResponse response = new MockHttpServletResponse(); + request.setServletPath("/pgtCallback"); + assertThat(filter.requiresAuthentication(request, response)).isFalse(); + filter.setProxyReceptorMatcher(PathPatternRequestMatcher.withDefaults().matcher(request.getServletPath())); + assertThat(filter.requiresAuthentication(request, response)).isFalse(); + filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class)); + assertThat(filter.requiresAuthentication(request, response)).isTrue(); + request.setRequestURI("/other"); + request.setServletPath("/other"); + assertThat(filter.requiresAuthentication(request, response)).isFalse(); + } + } diff --git a/docs/modules/ROOT/pages/migration/web.adoc b/docs/modules/ROOT/pages/migration/web.adoc index 6e99fd87df..7f5de0e194 100644 --- a/docs/modules/ROOT/pages/migration/web.adoc +++ b/docs/modules/ROOT/pages/migration/web.adoc @@ -94,6 +94,51 @@ switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(H ---- ====== +=== Migrate CAS Proxy Receptor Request Matcher + +Spring Security 6 converts any configured `proxyReceptorUrl` to a request matcher that matches the end of the request, that is `/**/proxy/receptor`. +In Spring Security 7, this pattern is not allowed and will change to using `PathPatternRequestMatcher`. +Also in Spring Security 7m the URL should by absolute, excluding any context path, like so: `/proxy/receptor`. + +So to prepare for these change, you can use `setProxyReceptorRequestMatcher` instead of `setProxyReceptorUrl`. + +That is, change this: +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +casAuthentication.setProxyReceptorUrl("/proxy/receptor"); +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +casAuthentication.setProxyReceptorUrl("/proxy/receptor") +---- +====== + +to this: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor")); +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor")) +---- +====== + == Include the Servlet Path Prefix in Authorization Rules For many applications <> will make no difference since most commonly all URIs listed are matched by the default servlet.