CSRF Protection
Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site when the user is authenticated.
Source: OWASP
There are several ways to defend yourself against a CSRF attack. The better approach is to use both the SameSite
cookie directive and a token-based technique to have an in-depth protection.
Note: CSRF protection only makes sense if your authentication system is based on cookies. This is why there is no example for Mobile+API applications.
#
SameSite Cookie AttributeThe SameSite
attribute is a new cookie directive to mitigate the risk of CSRF attacks. As of July 2019, SameSite attribute is on browsers used by 86,57% of Internet users.
#
Authentication with Session TokensIf you use session tokens with the setSessionCookie
, you can directly define the cookie directives in the configuration.
Example with config/default.json
Example with config/default.yml
#
Authentication with JSON Web TokensIf you use JSON Web Tokens, then you have to specify the directive manually when sending the token to the browser.
Example
#
Using CSRF TokensIn addition to the SameSite
directive it is strongly recommended to use a token-based mitigation technique to provide a robust defense.
Here is the principle:
- The server generates a token (stateless or stateful) and sends it to the browser (in the HTML page or in a separate cookie). An attacker performing a CSRF attack is not able to guess or read this token.
- In each subsequent POST, PUT, PATH or DELETE request, the client must include this token in a specific header, in the body of the request or in the URL parameters to prove the "origin" of the request.
- If the CSRF token is not present or is incorrect, the server returns an error 403 - FORBIDDEN with the message
Bad csrf token.
.
FoalTS token-based protection provides a hook and a function to set up the defense.
getCsrfToken
generates or reads the CSRF token.@CsrfTokenRequired
verifies the CSRF token when receiving requests and returns a 403 error if it is missing or incorrect.
The @CsrfTokenRequired
expects the CSRF token to be include in the request in either:
- the request body with the name
_csrf
, - the request query with the name
_csrf
, - or in one of these headers:
CSRF-Token
,XSRF-Token
,X-CSRF-Token
orX-XSRF-Token
.
#
Regular Web ApplicationsRegular Web Applications use Server-Side Rendering to generate their HTML pages.
#
Stateful CSRF token (Session-based)- Generate the token on login
- Include the token in each rendered page.
Home.html (example with a form)
home.html (example with JavaScript)
- Check the CSRF token on each subsequent POST, PUT, PATCH and DELETE request.
#
Stateless CSRF token (Double Submit Cookie Technique)If you want to use stateless CSRF tokens, you need to provide a base64-encoded secret in either:
a configuration file
Example with config/default.yml
or in a
.env
file or in an environment variable:
You can generate such a secret with the CLI command:
- Generate a token and send it in a cookie when rendering a page.
home.html (example with JavaScript)
- Check the CSRF token on each subsequent POST, PUT, PATCH and DELETE request.
#
SPA + APIIn Single-Page Application + API architecture, the frontend application is static and the pages are rendered in the browser.
First set the configuration key settings.csrf.cookie.maxAge
to a very large number (for example one year).
Example with config/default.json
Example with config/default.yml
#
Stateful CSRF token (Session-based)- Generate the token and send it in a cookie on login.
Your frontend application then must retreive the token from the cookie named csrfToken
and send it on each subsequent POST, PUT, PATCH or DELETE request (for example using the header CSRF-Token
).
- Check the CSRF token on each subsequent POST, PUT, PATCH and DELETE request.
#
Stateless CSRF token (Double Submit Cookie Technique)If you want to use stateless CSRF tokens, you need to provide a base64-encoded secret in either:
a configuration file
Example with config/default.yml
or in a
.env
file or in an environment variable:
You can generate such a secret with the CLI command:
- Generate a token and send it in a cookie on login.
Your frontend application then must retreive the token from the cookie named csrfToken
and send it on each subsequent POST, PUT, PATCH or DELETE request (for example using the header CSRF-Token
).
- Check the CSRF token on each subsequent POST, PUT, PATCH and DELETE request.
#
Disable the CSRF protectionThe CSRF hook @CsrfTokenRequired
can be disabled on a specific environment using the configuration key settings.csrf.enabled
.
Example with config/test.json
Example with config/test.yml
Example with environment variable
#
AdvancedThe directives of the cookie written by setCsrfCookie
can be override in the configuration.
Example with config/default.yml