Skip to content

Commit

Permalink
removed old CSRF token repostiory in favor of new Spring Sec 6+ prote…
Browse files Browse the repository at this point in the history
…ction mechanism
  • Loading branch information
albogdano committed Apr 27, 2024
1 parent 0c67d4f commit 3393b4b
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 279 deletions.

This file was deleted.

Expand Up @@ -17,8 +17,9 @@
*/
package com.erudika.para.server.security;

import java.util.regex.Pattern;
import com.erudika.para.core.utils.Para;
import jakarta.servlet.http.HttpServletRequest;
import java.util.regex.Pattern;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

Expand All @@ -37,6 +38,7 @@ public final class CsrfProtectionRequestMatcher implements RequestMatcher {
private final RegexRequestMatcher passAuthEndpoint = new RegexRequestMatcher("^/password_auth", null, true);
private final RegexRequestMatcher samlEndpoint = new RegexRequestMatcher("^/saml_auth.*", null, true);
private final RegexRequestMatcher samlMetaEndpoint = new RegexRequestMatcher("^/saml_metadata.*", null, true);
private final RegexRequestMatcher signinEndpoint = new RegexRequestMatcher("^" + Para.getConfig().signinPath() + ".*", null, true);

private CsrfProtectionRequestMatcher() {
}
Expand All @@ -49,7 +51,7 @@ public boolean matches(HttpServletRequest request) {
&& !samlEndpoint.matches(request)
&& !authEndpoints.matches(request)
&& !allowedMethods.matcher(request.getMethod()).matches();
return matches || passAuthEndpoint.matches(request);
return matches || passAuthEndpoint.matches(request) || signinEndpoint.matches(request);
}

}
Expand Up @@ -18,11 +18,15 @@
package com.erudika.para.server.security;

import com.erudika.para.core.utils.Para;
import static com.erudika.para.server.ParaServer.getInstance;
import com.typesafe.config.ConfigList;
import com.typesafe.config.ConfigObject;
import com.typesafe.config.ConfigValue;
import jakarta.annotation.security.DeclareRoles;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import org.slf4j.Logger;
Expand All @@ -36,7 +40,13 @@
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.web.filter.OncePerRequestFilter;

/**
* Programmatic configuration for Spring Security.
Expand All @@ -50,13 +60,11 @@ public class SecurityConfig {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private static final String[] DEFAULT_ROLES = {"USER", "MOD", "ADMIN", "APP"};

private final CachedCsrfTokenRepository csrfTokenRepository;

/**
* No-args constructor.
*/
public SecurityConfig() {
csrfTokenRepository = getInstance(CachedCsrfTokenRepository.class);
}

/**
Expand Down Expand Up @@ -95,8 +103,18 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
parseProtectedResources(http, protectedResources);

if (Para.getConfig().csrfProtectionEnabled()) {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler();
// set the name of the attribute the CsrfToken will be populated on
delegate.setCsrfRequestAttributeName("_csrf");
// Use only the handle() method of XorCsrfTokenRequestAttributeHandler and the
// default implementation of resolveCsrfTokenValue() from CsrfTokenRequestHandler
CsrfTokenRequestHandler requestHandler = delegate::handle;
http.csrf((csrf) -> csrf.requireCsrfProtectionMatcher(CsrfProtectionRequestMatcher.INSTANCE).
csrfTokenRepository(csrfTokenRepository));
csrfTokenRepository(tokenRepository).csrfTokenRequestHandler(requestHandler))
.addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class);
// http.csrf((csrf) -> csrf.requireCsrfProtectionMatcher(CsrfProtectionRequestMatcher.INSTANCE).
// csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
} else {
http.csrf((csrf) -> csrf.disable());
}
Expand Down Expand Up @@ -159,4 +177,16 @@ private void parseProtectedResources(HttpSecurity http, ConfigObject protectedRe
}
}
}

private static final class CsrfCookieFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
// Render the token value to a cookie by causing the deferred token to be loaded
csrfToken.getToken();
filterChain.doFilter(request, response);
}
}
}

0 comments on commit 3393b4b

Please sign in to comment.