Cross-site request forgeries (CSRF) are a type of social engineering attack in which a malicious agent tricks a user into submitting a valid, but unintended request to your server. This can happen, for example, when a user opens a malicious email or website while they are still signed in to your website.
By exploiting the default behavior of certain types of HTML tags, the malicious source can cause your client's browser to automatically submit a particular request to your server. This request could be anything from "post a message" on an online forum, to "transfer money to account XXXXXX" in a banking system!
The simplest way to reliably defend against CSRF attacks is by using a cryptographically secure secret token in any part of your client-side application that is capable of performing state-changing operations on the user's account (typically forms and Javascript widgets that can submit POST, PUT, or DELETE requests).
The idea is that when your server receives one of these requests, it must contain the secret token issued earlier. Requests made through a legitimate portion of your application will have the secret token embedded in them, while forgeries will not - and cannot - because they do not have the ability to retrieve data from the user's session.
UserFrosting uses the Slim CSRF Guard middleware to automatically generate new CSRF tokens and check for them at the beginning of POST, PUT, DELETE and PATCH requests. The tokens consist of a name-value pair. All that is necessary from the developer point of view is to inject the CSRF tokens into any point in the application where a user could make one of these types of requests.
The easiest way to add the CSRF tokens to a form is by including the partial Twig template components/csrf.html.twig
. Simply add this after the opening <form>
tag:
<form id="sign-in" role="form" action="{{site.uri.public}}/account/login" method="post">
{% include "components/csrf.html.twig" %}
...
</form>
This will automatically add the hidden input fields csrf_name
and csrf_value
to your form, along with their values.
Not all requests that require CSRF protection originate from HTML forms. To inject the tokens into AJAX requests, you may access them via the global site
Javascript variable.
var url = site.uri.public + '/api/users/u/bob';
var data = {
// Put whatever data you are submitting here
};
data[site.csrf.keys.name] = site.csrf.name;
data[site.csrf.keys.value] = site.csrf.value;
$.ajax({
type: 'PUT',
url: url,
data: data
});
The Javascript
site
variable is declared in thecomponents/config.js.twig
template.
Sometimes, you need to bypass CSRF protection for certain POST, PUT, or DELETE requests. For example, if you are creating an API that is not meant for consumption by a user via a browser, but rather by some other application.
Currently, the CSRF middleware does not offer a native option to whitelist specific routes. For now, you can modify your index.php
to ignore the CSRF middleware for certain requests based on a matching pattern. For example:
...
$request = $container->request;
$path = $request->getUri()->getPath();
if (!$path || !starts_with($path, [
'api/hoots',
'api/screeches'
])) {
$app->add($container->csrf);
}