Skip to content

Commit 72d4300

Browse files
Update the excludedPaths from portalCheckFilter in web.xml to be sharable for other configs (#8769)
* Update AudienceAccessTokenValidator.java Fix logic * Refactor excluded path to be accessible from other config * add missing import
1 parent 0d325b0 commit 72d4300

4 files changed

Lines changed: 123 additions & 41 deletions

File tree

core/src/main/java/org/fao/geonet/kernel/security/keycloak/KeycloakPreAuthActionsLoginFilter.java

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,24 @@
3535
import org.springframework.security.core.context.SecurityContextHolder;
3636
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
3737
import org.springframework.security.web.csrf.CsrfFilter;
38-
39-
import javax.servlet.FilterChain;
40-
import javax.servlet.ServletException;
41-
import javax.servlet.ServletRequest;
42-
import javax.servlet.ServletResponse;
38+
import javax.servlet.*;
4339
import javax.servlet.http.HttpServletRequest;
4440
import javax.servlet.http.HttpServletResponse;
4541
import java.io.IOException;
4642
import java.net.URLEncoder;
43+
import org.apache.commons.lang3.StringUtils;
44+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
45+
import org.springframework.web.context.ServletContextAware;
46+
import java.util.ArrayList;
47+
import java.util.Arrays;
48+
import java.util.List;
49+
import java.util.stream.Collectors;
4750

48-
public class KeycloakPreAuthActionsLoginFilter extends KeycloakPreAuthActionsFilter {
51+
/**
52+
* This class extends the KeycloakPreAuthActionsFilter to handle pre-authentication actions
53+
* specific to Keycloak integration in GeoNetwork.
54+
*/
55+
public class KeycloakPreAuthActionsLoginFilter extends KeycloakPreAuthActionsFilter implements ServletContextAware {
4956

5057
@Autowired
5158
LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint;
@@ -63,6 +70,38 @@ public KeycloakPreAuthActionsLoginFilter(UserSessionManagement userSessionManage
6370
csrfFilter.setRequireCsrfProtectionMatcher(csrfRequestMatcher);
6471
}
6572

73+
/**
74+
* The servlet context parameter name that contains the excluded URL paths.
75+
* This is used to configure which paths should be ignored by the filter.
76+
* Based on the GeoNetworkPortalFilter configured in web.xml
77+
*/
78+
private static final String EXCLUDED_URL_PATHS = "excludedPaths";
79+
80+
/**
81+
* RequestMatchers for the ignored application paths.
82+
*/
83+
private List<AntPathRequestMatcher> excludedPathsMatchers = new ArrayList<>();
84+
85+
/**
86+
* The Method to set the servlet context from the web.xml.
87+
* It also sets the request matchers for the excluded paths.
88+
*/
89+
public void setServletContext(ServletContext servletContext) {
90+
//get excluded paths from servlet context in web.xml
91+
String excludedPathsValue = servletContext.getInitParameter(EXCLUDED_URL_PATHS);
92+
93+
if (StringUtils.isNotEmpty(excludedPathsValue)) {
94+
excludedPathsMatchers = Arrays.stream(excludedPathsValue.split(","))
95+
.map(StringUtils::trimToEmpty)
96+
.filter(StringUtils::isNotEmpty)
97+
.map(AntPathRequestMatcher::new)
98+
.collect(Collectors.toList());
99+
}
100+
101+
// add the jwks endpoint to the excluded paths
102+
excludedPathsMatchers.add(new AntPathRequestMatcher("/.well-known/jwks.json"));
103+
}
104+
66105
@Override
67106
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
68107
throws IOException, ServletException {
@@ -76,6 +115,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
76115
// No sign in page required for api calls.
77116
// - and it is not an internal k_* request which should be processed by keycloak adapter and also don't required login page.
78117
if (servletRequest.getPathInfo() != null &&
118+
excludedPathsMatchers.stream()
119+
.noneMatch(matcher -> matcher.matches(servletRequest)) &&
79120
!KeycloakAuthenticationProcessingFilter.DEFAULT_REQUEST_MATCHER.matches(servletRequest) &&
80121
!isAuthenticated() &&
81122
!(servletRequest.getContextPath() + KeycloakUtil.getSigninPath()).equals(servletRequest.getRequestURI()) &&

core/src/main/java/org/fao/geonet/kernel/security/openidconnect/GeonetworkOidcPreAuthActionsLoginFilter.java

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,20 @@
3434
import javax.servlet.http.HttpServletResponse;
3535
import java.io.IOException;
3636
import java.net.URLEncoder;
37+
import org.apache.commons.lang3.StringUtils;
38+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
39+
import org.springframework.web.context.ServletContextAware;
40+
import java.util.ArrayList;
41+
import java.util.Arrays;
42+
import java.util.List;
43+
import java.util.stream.Collectors;
44+
3745

3846
/**
3947
* Filter implementation for handling pre-authentication actions for OpenID Connect (OIDC) login.
4048
* This filter checks if the user is authenticated and redirects unauthenticated users to the login page.
4149
*/
42-
public class GeonetworkOidcPreAuthActionsLoginFilter implements Filter {
50+
public class GeonetworkOidcPreAuthActionsLoginFilter implements Filter, ServletContextAware {
4351

4452
/**
4553
* Repository for managing client registrations for OpenID Connect.
@@ -49,10 +57,40 @@ public class GeonetworkOidcPreAuthActionsLoginFilter implements Filter {
4957
private ClientRegistrationRepository clientRegistrationRepository;
5058

5159

60+
/**
61+
* The servlet context parameter name that contains the excluded URL paths.
62+
* This is used to configure which paths should be ignored by the filter.
63+
* Based on the GeoNetworkPortalFilter configured in web.xml
64+
*/
65+
private static final String EXCLUDED_URL_PATHS = "excludedPaths";
5266

53-
@Override
54-
public void init(FilterConfig filterConfig) throws ServletException {
67+
/**
68+
* RequestMatchers for the ignored application paths.
69+
*/
70+
private List<AntPathRequestMatcher> excludedPathsMatchers = new ArrayList<>();
5571

72+
/**
73+
* The Method to set the servlet context from the web.xml.
74+
* It also sets the request matchers for the excluded paths.
75+
*/
76+
public void setServletContext(ServletContext servletContext) {
77+
//get excluded paths from servlet context in web.xml
78+
String excludedPathsValue = servletContext.getInitParameter(EXCLUDED_URL_PATHS);
79+
80+
if (StringUtils.isNotEmpty(excludedPathsValue)) {
81+
excludedPathsMatchers = Arrays.stream(excludedPathsValue.split(","))
82+
.map(StringUtils::trimToEmpty)
83+
.filter(StringUtils::isNotEmpty)
84+
.map(AntPathRequestMatcher::new)
85+
.collect(Collectors.toList());
86+
}
87+
88+
// add the jwks endpoint to the excluded paths
89+
excludedPathsMatchers.add(new AntPathRequestMatcher("/.well-known/jwks.json"));
90+
}
91+
92+
@Override
93+
public void init(FilterConfig config) {
5694
}
5795

5896
/**
@@ -82,8 +120,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
82120
SecurityContextHolder.getContext().getAuthentication().isAuthenticated() &&
83121
!(SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken);
84122

85-
boolean isPublicEndpoint =
86-
requestUri.endsWith("/.well-known/jwks.json");
123+
boolean isPublicEndpoint = excludedPathsMatchers.stream()
124+
.anyMatch(matcher -> matcher.matches(servletRequest));
87125

88126
if (!isAuthenticated && !isLoginRequest && !isPublicEndpoint && !isBearerTokenAccess) {
89127
String returningUrl = requestUri +

core/src/main/java/org/fao/geonet/web/GeoNetworkPortalFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ public class GeoNetworkPortalFilter implements javax.servlet.Filter {
5858

5959
@Override
6060
public void init(FilterConfig config) {
61-
String excludedPathsValue = config.getInitParameter(EXCLUDED_URL_PATHS);
61+
ServletContext context = config.getServletContext();
62+
String excludedPathsValue = context.getInitParameter(EXCLUDED_URL_PATHS);
6263
if (StringUtils.isNotEmpty(excludedPathsValue)) {
6364
excludedPathsMatchers = Arrays.stream(excludedPathsValue.split(","))
6465
.map(StringUtils::trimToEmpty)

web/src/main/webResources/WEB-INF/web.xml

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -82,43 +82,45 @@
8282
<url-pattern>/*</url-pattern>
8383
</filter-mapping>
8484

85+
8586
<!-- Filter to verify the portal parameter in the URL is a valid portal defined in GeoNetwork.
8687
If a non-valid value is provided, it redirects to the same URL in the default portal (srv).
8788
-->
8889
<filter>
8990
<filter-name>portalCheckFilter</filter-name>
9091
<filter-class>org.fao.geonet.web.GeoNetworkPortalFilter</filter-class>
91-
<init-param>
92+
</filter>
93+
94+
<context-param>
95+
<param-name>excludedPaths</param-name>
96+
<param-value>
9297
<!-- List of Ant style patterns that should be not checked for application URL paths -->
9398
<!-- https://docs.spring.io/spring-security/site/docs/5.7.3/api/org/springframework/security/web/util/matcher/AntPathRequestMatcher.html -->
94-
<param-name>excludedPaths</param-name>
95-
<param-value>
96-
/catalog/**,
97-
/api/**,
98-
/static/**,
99-
/images/**,
100-
/index/features/**,
101-
/htmlcache/**,
102-
/config/**,
103-
/jolokia/**,
104-
/dashboards/**,
105-
/criticalhealthcheck/**,
106-
/warninghealthcheck/**,
107-
/expensivehealthcheck/**,
108-
/monitor/**,
109-
/doc/**,
110-
/map/**,
111-
/pdf/**,
112-
/xml/**,
113-
/xsl/**,
114-
/read/**,
115-
/opensearch/**,
116-
/.*.jsp,
117-
/*.html,
118-
/*.css
119-
</param-value>
120-
</init-param>
121-
</filter>
99+
/catalog/**,
100+
/api/**,
101+
/static/**,
102+
/images/**,
103+
/index/features/**,
104+
/htmlcache/**,
105+
/config/**,
106+
/jolokia/**,
107+
/dashboards/**,
108+
/criticalhealthcheck/**,
109+
/warninghealthcheck/**,
110+
/expensivehealthcheck/**,
111+
/monitor/**,
112+
/doc/**,
113+
/map/**,
114+
/pdf/**,
115+
/xml/**,
116+
/xsl/**,
117+
/read/**,
118+
/opensearch/**,
119+
/.*.jsp,
120+
/*.html,
121+
/*.css
122+
</param-value>
123+
</context-param>
122124

123125
<filter-mapping>
124126
<filter-name>portalCheckFilter</filter-name>

0 commit comments

Comments
 (0)