Class CsrfPreventionFilter
java.lang.Object
org.camunda.bpm.webapp.impl.security.filter.CsrfPreventionFilter
- All Implemented Interfaces:
jakarta.servlet.Filter
Provides basic CSRF protection implementing a Same Origin Standard Header verification (step 1)
and a Synchronization Token with a cookie-stored token on the front-end.
This token is called XSRF-TOKEN, generated by the server, sent in the first response as a Cookie, then stored as a client Cookie, and sent back as an HTTP header (X-XSRF-TOKEN) on subsequent requests.
Positive scenario: Client Server | | | GET Fetch Request \| JSESSIONID |---------------------------------| XSRF-TOKEN | /| pair generation |/Response to Fetch Request | |---------------------------------| JSESSIONID |\ | XSRF-TOKEN | | pair cached | POST Request with valid token \| JSESSIONID | header | |---------------------------------| XSRF-TOKEN | /| pair validation |/ Response to POST Request | |---------------------------------| |\ | Negative scenario: Client Server | | | POST Request without token | JSESSIONID | header \| XSRF-TOKEN |---------------------------------| pair validation | /| |/Request is rejected | |---------------------------------| |\ | Client Server | | | POST Request with invalid token\| JSESSIONID |---------------------------------| XSRF-TOKEN | /| pair validation |/Request is rejected | |---------------------------------| |\ |Parts of this code were ported from the
CsrfPreventionFilter
class
of Apache Tomcat. Furthermore, the RestCsrfPreventionFilter
class from
the same codebase was used as a guideline.- Author:
- Nikola Koevski
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid
destroy()
void
doFilter
(jakarta.servlet.ServletRequest servletRequest, jakarta.servlet.ServletResponse servletResponse, jakarta.servlet.FilterChain filterChain) protected boolean
doSameOriginStandardHeadersVerification
(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) Validates if the Origin/Referer header matches the provided target origin.protected boolean
doTokenValidation
(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) Validates the provided CSRF token value from the request with the session CSRF token value.protected String
Generate a one-time token for authenticating subsequent requests.protected String
getCookiePath
(jakarta.servlet.http.HttpServletRequest request) int
void
init
(jakarta.servlet.FilterConfig filterConfig) protected boolean
isNonModifyingRequest
(jakarta.servlet.http.HttpServletRequest request) Determine if the request a non-modifying request.protected void
setCSRFToken
(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) Generates a new CSRF Token which is persisted in the session.void
setDenyStatus
(int denyStatus) Sets the response status code that is used to reject denied request.void
setEntryPoints
(String entryPoints) Entry points are URLs that will not be tested for the presence of a valid token.void
setRandomClass
(String randomClass) Sets the name of the class to use to generate tokens.void
setTargetOrigin
(String targetOrigin) Target origin is the application expected deployment domain, i.e.
-
Field Details
-
entryPoints
-
cookieConfigurator
-
-
Constructor Details
-
CsrfPreventionFilter
public CsrfPreventionFilter()
-
-
Method Details
-
init
public void init(jakarta.servlet.FilterConfig filterConfig) throws jakarta.servlet.ServletException - Specified by:
init
in interfacejakarta.servlet.Filter
- Throws:
jakarta.servlet.ServletException
-
doFilter
public void doFilter(jakarta.servlet.ServletRequest servletRequest, jakarta.servlet.ServletResponse servletResponse, jakarta.servlet.FilterChain filterChain) throws IOException, jakarta.servlet.ServletException - Specified by:
doFilter
in interfacejakarta.servlet.Filter
- Throws:
IOException
jakarta.servlet.ServletException
-
doTokenValidation
protected boolean doTokenValidation(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) throws IOException Validates the provided CSRF token value from the request with the session CSRF token value.- Parameters:
request
-response
-- Returns:
- true if the token is valid
- Throws:
IOException
-
doSameOriginStandardHeadersVerification
protected boolean doSameOriginStandardHeadersVerification(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) throws IOException Validates if the Origin/Referer header matches the provided target origin.- Parameters:
request
-response
-- Returns:
- true if the values match
- Throws:
IOException
-
setCSRFToken
protected void setCSRFToken(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) Generates a new CSRF Token which is persisted in the session. How the token is forwarded to the client and how it will be persisted there is not covered by this method.- Parameters:
request
-
-
getCookiePath
-
getTargetOrigin
-
setTargetOrigin
Target origin is the application expected deployment domain, i.e. the domain name through which the webapps are accessed. If nothing is set, the "Same Origin with Standard Headers" verification is not performed.- Parameters:
targetOrigin
- The application's domain name together with the protocol and port (ex. http://example.com:8080)- Throws:
MalformedURLException
-
setEntryPoints
Entry points are URLs that will not be tested for the presence of a valid token. They are used to provide a way to navigate back to a protected application after navigating away from it. Entry points will be limited to HTTP GET requests and should not trigger any security sensitive actions.- Parameters:
entryPoints
- Comma separated list of URLs to be configured as entry points.
-
getDenyStatus
public int getDenyStatus()- Returns:
- the response status code that is used to reject a denied request.
-
setDenyStatus
public void setDenyStatus(int denyStatus) Sets the response status code that is used to reject denied request. If none is set, the default value of 403 will be used.- Parameters:
denyStatus
- HTTP status code
-
getRandomClass
-
setRandomClass
Sets the name of the class to use to generate tokens. The class must be an instance of `java.util.Random`. If not set, the default value of `java.security.SecureRandom` will be used.- Parameters:
randomClass
- The name of the class
-
destroy
public void destroy()- Specified by:
destroy
in interfacejakarta.servlet.Filter
-
isNonModifyingRequest
protected boolean isNonModifyingRequest(jakarta.servlet.http.HttpServletRequest request) Determine if the request a non-modifying request. A non-modifying request is one that is either a 'HTTP GET/OPTIONS/HEAD' request, or is allowed explicitly through the 'entryPoints' parameter in the web.xml- Returns:
- true if the request is a non-modifying request
-
generateCSRFToken
Generate a one-time token for authenticating subsequent requests.- Returns:
- the generated token
-