diff --git a/src/extension/security/cas/src/main/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilter.java b/src/extension/security/cas/src/main/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilter.java
index 9ddf4dc84e9..f6d611541e0 100644
--- a/src/extension/security/cas/src/main/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilter.java
+++ b/src/extension/security/cas/src/main/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilter.java
@@ -16,6 +16,7 @@
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@@ -24,6 +25,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import org.geoserver.ows.URLMangler;
+import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.security.LogoutFilterChain;
import org.geoserver.security.config.SecurityNamedServiceConfig;
@@ -31,6 +34,7 @@
import org.geoserver.security.filter.GeoServerPreAuthenticatedUserNameFilter;
import org.geoserver.security.impl.GeoServerRole;
import org.geoserver.security.impl.RoleCalculator;
+import org.geotools.util.logging.Logging;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.session.SingleSignOutHandler;
@@ -59,6 +63,8 @@
public class GeoServerCasAuthenticationFilter extends GeoServerPreAuthenticatedUserNameFilter
implements LogoutHandler {
+ private static final Logger LOGGER = Logging.getLogger(GeoServerCasAuthenticationFilter.class);
+
protected Cas20ProxyTicketValidator validator;
protected ServiceAuthenticationDetailsSource casAuthenticationDetailsSource;
protected String casLogoutURL;
@@ -136,14 +142,15 @@ protected Assertion getCASAssertion(HttpServletRequest request) {
protected static String retrieveService(HttpServletRequest request) {
- String serviceBaseUrl = null;
- String proxyBaseUrl = GeoServerExtensions.getProperty("PROXY_BASE_URL");
- if (StringUtils.hasLength(proxyBaseUrl)) {
- serviceBaseUrl = proxyBaseUrl;
- } else {
- serviceBaseUrl = request.getRequestURL().toString();
- }
- StringBuffer buff = new StringBuffer(serviceBaseUrl);
+ String requestBaseUrl = ResponseUtils.baseURL(request);
+ String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+
+ // Will run the URL through various manglers, to handle proxying, etc.
+ String serviceBaseUrl =
+ ResponseUtils.buildURL(
+ requestBaseUrl, requestPath, null, URLMangler.URLType.SERVICE);
+
+ StringBuilder buff = new StringBuilder(serviceBaseUrl);
if (StringUtils.hasLength(request.getQueryString())) {
String query = request.getQueryString();
diff --git a/src/extension/security/cas/src/test/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilterTest.java b/src/extension/security/cas/src/test/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilterTest.java
new file mode 100644
index 00000000000..e7d8c42b141
--- /dev/null
+++ b/src/extension/security/cas/src/test/java/org/geoserver/security/cas/GeoServerCasAuthenticationFilterTest.java
@@ -0,0 +1,143 @@
+/* (c) 2024 Open Source Geospatial Foundation - all rights reserved
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+package org.geoserver.security.cas;
+
+import static org.junit.Assert.assertEquals;
+
+import org.geoserver.config.GeoServer;
+import org.geoserver.config.GeoServerInfo;
+import org.geoserver.ows.HTTPHeadersCollector;
+import org.geoserver.ows.ProxifyingURLMangler;
+import org.geoserver.test.GeoServerSystemTestSupport;
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+public class GeoServerCasAuthenticationFilterTest extends GeoServerSystemTestSupport {
+
+ @Test
+ public void testRetrieveServiceWithNoProxyBaseUrl() {
+ GeoServer geoServer = getGeoServer();
+ String oldValue = System.getProperty("PROXY_BASE_URL");
+ try {
+ setProxyBase(geoServer, null);
+ setSystemProperty("PROXY_BASE_URL", null);
+
+ MockHttpServletRequest request =
+ buildMockRequest(
+ "http",
+ "localhost",
+ 8080,
+ "/geoserver",
+ "/geoserver/myworkspace/wms?SERVICE=WMS");
+
+ String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);
+
+ assertEquals("http://localhost:8080/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
+ } finally {
+ // Reset to make sure we don't interfere with other tests at all
+ setSystemProperty("PROXY_BASE_URL", oldValue);
+ }
+ }
+
+ @Test
+ public void testRetrieveServiceWithProxyBaseUrlSystemProperty() {
+
+ String oldValue = System.getProperty("PROXY_BASE_URL");
+ try {
+ setSystemProperty("PROXY_BASE_URL", "https://example.com/geoserver");
+
+ MockHttpServletRequest request =
+ buildMockRequest(
+ "http",
+ "localhost",
+ 8080,
+ "/geoserver",
+ "/geoserver/myworkspace/wms?SERVICE=WMS");
+
+ String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);
+
+ assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
+ } finally {
+ // Reset to make sure we don't interfere with other tests at all
+ setSystemProperty("PROXY_BASE_URL", oldValue);
+ }
+ }
+
+ @Test
+ public void testRetrieveServiceWithProxyBaseUrlConfig() {
+ GeoServer geoServer = getGeoServer();
+ try {
+ setProxyBase(geoServer, "https://example.com/geoserver");
+
+ MockHttpServletRequest request =
+ buildMockRequest(
+ "http",
+ "localhost",
+ 8080,
+ "/geoserver",
+ "/geoserver/myworkspace/wms?SERVICE=WMS");
+
+ String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);
+
+ assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
+ } finally {
+ setProxyBase(geoServer, null);
+ }
+ }
+
+ @Test
+ public void testRetrieveServiceWithProxyBaseUrlConfigAndParameterization() {
+ GeoServer geoServer = getGeoServer();
+ try {
+ setProxyBase(geoServer, "https://${X-Forwarded-Host}/geoserver");
+
+ MockHttpServletRequest request =
+ buildMockRequest(
+ "http",
+ "localhost",
+ 8080,
+ "/geoserver",
+ "/geoserver/myworkspace/wms?SERVICE=WMS");
+
+ // Add headers
+ request.addHeader(
+ ProxifyingURLMangler.Headers.FORWARDED_HOST.asString(), "example.com");
+ HTTPHeadersCollector filter = new HTTPHeadersCollector();
+ filter.collectHeaders(request);
+
+ String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);
+
+ assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
+ } finally {
+ setProxyBase(geoServer, null);
+ }
+ }
+
+ private MockHttpServletRequest buildMockRequest(
+ String scheme, String serverName, int port, String contextPath, String uri) {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setScheme(scheme);
+ request.setServerName(serverName);
+ request.setServerPort(port);
+ request.setContextPath(contextPath);
+ request.setRequestURI(uri);
+ return request;
+ }
+
+ private void setProxyBase(GeoServer gs, String s) {
+ final GeoServerInfo global = gs.getGlobal();
+ global.getSettings().setProxyBaseUrl(s);
+ global.getSettings().setUseHeadersProxyURL(s != null);
+ gs.save(global);
+ }
+
+ private void setSystemProperty(String key, String value) {
+ if (value == null) {
+ System.clearProperty(key);
+ } else {
+ System.setProperty(key, value);
+ }
+ }
+}
diff --git a/src/gwc/pom.xml b/src/gwc/pom.xml
index 280c1001490..50434b01a6c 100644
--- a/src/gwc/pom.xml
+++ b/src/gwc/pom.xml
@@ -131,6 +131,12 @@
tests
test
+
+ org.geotools
+ gt-iau-wkt
+ ${gt.version}
+ test
+