Skip to content

Commit 187c836

Browse files
committed
Refactored the CSRF docs
1 parent 795b782 commit 187c836

File tree

6 files changed

+121
-156
lines changed

6 files changed

+121
-156
lines changed

_build/redirection_map

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
/cookbook/console/style /console/style
125125
/cookbook/console/usage /console
126126
/console/usage /console
127-
/cookbook/controller/csrf_token_validation /controller/csrf_token_validation
127+
/cookbook/controller/csrf_token_validation /security/csrf
128128
/cookbook/controller/error_pages /controller/error_pages
129129
/cookbook/controller/forwarding /controller/forwarding
130130
/cookbook/controller/index /controller
@@ -221,7 +221,7 @@
221221
/cookbook/security/acl /security/acl
222222
/cookbook/security/acl_advanced /security/acl_advanced
223223
/cookbook/security/api_key_authentication /security/api_key_authentication
224-
/cookbook/security/csrf_in_login_form /security/csrf_in_login_form
224+
/cookbook/security/csrf_in_login_form /security/csrf
225225
/cookbook/security/custom_authentication_provider /security/custom_authentication_provider
226226
/cookbook/security/custom_password_authenticator /security/custom_password_authenticator
227227
/cookbook/security/custom_provider /security/custom_provider
@@ -361,7 +361,9 @@
361361
/components/yaml/introduction /components/yaml
362362
/components/yaml/index /components/yaml
363363
/console/logging /console
364+
/controller/csrf_token_validation /security/csrf
364365
/deployment/tools /deployment
366+
/form/csrf_protection /security/csrf
365367
/install/bundles /setup/bundles
366368
/email/gmail /email
367369
/email/cloud /email
@@ -376,6 +378,7 @@
376378
/frontend/assetic/yuicompressor /frontend/assetic
377379
/reference/configuration/assetic /frontend/assetic
378380
/security/target_path /security
381+
/security/csrf_in_login_form /security/csrf
379382
/service_container/third_party /service_container
380383
/templating/templating_service /templates
381384
/testing/simulating_authentication /testing/http_authentication

controller/csrf_token_validation.rst

Lines changed: 0 additions & 17 deletions
This file was deleted.

form/csrf_protection.rst

Lines changed: 0 additions & 74 deletions
This file was deleted.

reference/configuration/framework.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ csrf_protection
411411

412412
.. seealso::
413413

414-
For more information about CSRF protection in forms, see :doc:`/form/csrf_protection`.
414+
For more information about CSRF protection, see :doc:`/security/csrf`.
415415

416416
.. _reference-csrf_protection-enabled:
417417

@@ -422,7 +422,7 @@ enabled
422422
otherwise
423423

424424
This option can be used to disable CSRF protection on *all* forms. But you
425-
can also :ref:`disable CSRF protection on individual forms <form-disable-csrf>`.
425+
can also :ref:`disable CSRF protection on individual forms <form-csrf-customization>`.
426426

427427
If you're using forms, but want to avoid starting your session (e.g. using
428428
forms in an API-only website), ``csrf_protection`` will need to be set to

security.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ Authentication (Identifying/Logging in the User)
12911291
security/api_key_authentication
12921292
security/custom_authentication_provider
12931293
security/pre_authenticated
1294-
security/csrf_in_login_form
1294+
security/csrf
12951295
security/named_encoders
12961296
security/multiple_user_providers
12971297
security/multiple_guard_authenticators

security/csrf_in_login_form.rst renamed to security/csrf.rst

Lines changed: 113 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,92 @@
11
.. index::
2-
single: Security; CSRF Protection in the Login Form
2+
single: CSRF; CSRF protection
33

4-
Using CSRF Protection in the Login Form
5-
=======================================
4+
How to Implement CSRF Protection
5+
================================
66

7-
When using a login form, you should make sure that you are protected against CSRF
8-
(`Cross-site request forgery`_). The Security component already has built-in support
9-
for CSRF. In this article you'll learn how you can use it in your login form.
7+
CSRF - or `Cross-site request forgery`_ - is a method by which a malicious
8+
user attempts to make your legitimate users unknowingly submit data that
9+
they don't intend to submit.
1010

11-
.. note::
11+
CSRF protection works by adding a hidden field to your form that contains a
12+
value that only you and your user knows. This ensures that the user - not some
13+
other entity - is submitting the given data.
1214

13-
Login CSRF attacks are a bit less well-known. See `Forging Login Requests`_
14-
if you're curious about more details.
15+
Before enabling the CSRF protection, install the CSRF support in your project
16+
(which in turn requires installing the Symfony Form component):
1517

16-
Configuring CSRF Protection
17-
---------------------------
18+
.. code-block:: terminal
1819
19-
First, make sure that the CSRF protection is enabled in the main configuration
20-
file:
20+
$ composer require security-csrf form
2121
22-
.. configuration-block::
22+
CSRF Protection in Symfony Forms
23+
--------------------------------
2324

24-
.. code-block:: yaml
25+
Forms created with the Symfony Form component include CSRF tokens by default
26+
and Symfony checks them automatically, so you don't have to anything to be
27+
protected against CSRF attacks.
2528

26-
# config/packages/framework.yaml
27-
framework:
28-
# ...
29-
csrf_protection: { enabled: true }
29+
This automatic protection is enabled/disabled with the ``csrf_protection`` in
30+
the ``config/packages/framework.yaml`` file. For more information, see the
31+
:ref:`form configuration reference <reference-framework-form>`.
3032

31-
.. code-block:: xml
33+
.. _form-csrf-customization:
3234

33-
<!-- config/packages/framework.xml -->
34-
<?xml version="1.0" encoding="UTF-8" ?>
35-
<container xmlns="http://symfony.com/schema/dic/services"
36-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
37-
xmlns:framework="http://symfony.com/schema/dic/symfony"
38-
xsi:schemaLocation="http://symfony.com/schema/dic/services
39-
http://symfony.com/schema/dic/services/services-1.0.xsd
40-
http://symfony.com/schema/dic/symfony
41-
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
35+
By default Symfony adds the CSRF token in a hidden field called ``_token``, but
36+
this can be customized on a form-by-form basis::
4237

43-
<framework:config>
44-
<framework:csrf-protection enabled="true" />
45-
</framework:config>
46-
</container>
38+
// ...
39+
use App\Entity\Task;
40+
use Symfony\Component\OptionsResolver\OptionsResolver;
4741

48-
.. code-block:: php
42+
class TaskType extends AbstractType
43+
{
44+
// ...
4945

50-
// config/packages/framework.php
51-
$container->loadFromExtension('framework', array(
52-
'csrf_protection' => null,
53-
));
46+
public function configureOptions(OptionsResolver $resolver)
47+
{
48+
$resolver->setDefaults(array(
49+
'data_class' => Task::class,
50+
// enable/disable CSRF protection for this form
51+
'csrf_protection' => true,
52+
// the name of the hidden HTML field that stores the token
53+
'csrf_field_name' => '_token',
54+
// an arbitrary string used to generate the value of the token
55+
// using a different string for each form improves its security
56+
'csrf_token_id' => 'task_item',
57+
));
58+
}
59+
60+
// ...
61+
}
62+
63+
.. caution::
64+
65+
Since the token is stored in the session, a session is started automatically
66+
as soon as you render a form with CSRF protection.
67+
68+
.. caution::
69+
70+
CSRF tokens are meant to be different for every user. Beware of that when
71+
caching pages that include forms containing CSRF tokens. For more
72+
information, see :doc:`/http_cache/form_csrf_caching`.
73+
74+
CSRF Protection in Login Forms
75+
------------------------------
76+
77+
`Login CSRF attacks`_ can be prevented using the same technique of adding hidden
78+
CSRF tokens into the login forms. The Security component already provides CSRF
79+
protection, but you need to configure some options before using it.
80+
81+
.. tip::
82+
83+
If you're using a :doc:`Guard Authenticator </security/guard_authentication>`,
84+
you'll need to validate the CSRF token manually inside of that class. See
85+
:ref:`guard-csrf-protection` for details.
5486

55-
Then, the security component needs a CSRF token provider. You can set this to
56-
use the default provider available in the security component:
87+
First, configure the CSRF token provider used by the form login in your security
88+
configuration. You can set this to use the default provider available in the
89+
security component:
5790

5891
.. configuration-block::
5992

@@ -107,26 +140,12 @@ use the default provider available in the security component:
107140
),
108141
));
109142
110-
The Security component can be configured further, but this is all information
111-
it needs to be able to use CSRF in the login form.
112-
113-
.. tip::
114-
115-
If you're using a :doc:`Guard Authenticator </security/guard_authentication>`,
116-
you'll need to validate the CSRF token manually inside of that class. See
117-
:ref:`guard-csrf-protection` for details.
118-
119143
.. _csrf-login-template:
120144

121-
Rendering the CSRF field
122-
------------------------
123-
124-
Now that Security component will check for the CSRF token, you have to add
125-
a *hidden* field to the login form containing the CSRF token. By default,
126-
this field is named ``_csrf_token``. That hidden field must contain the CSRF
127-
token, which can be generated by using the ``csrf_token()`` function. That
128-
function requires a token ID, which must be set to ``authenticate`` when
129-
using the login form:
145+
Then, use the ``csrf_token()`` function in the Twig template to generate a CSRF
146+
token and store it as a hidden field of the form. By default, the HTML field
147+
must be called ``_csrf_token`` and the string used to generate the value must
148+
be ``authenticate``:
130149

131150
.. configuration-block::
132151

@@ -223,5 +242,39 @@ After this, you have protected your login form against CSRF attacks.
223242
),
224243
));
225244
226-
.. _`Cross-site request forgery`: https://en.wikipedia.org/wiki/Cross-site_request_forgery
227-
.. _`Forging Login Requests`: https://en.wikipedia.org/wiki/Cross-site_request_forgery#Forging_login_requests
245+
CSRF Protection in HTML Forms
246+
-----------------------------
247+
248+
It's also possible to add CSRF protection to regular HTML forms not managed by
249+
the Symfony Form component, for example the simple forms used to delete items.
250+
First, use the ``csrf_token()`` function in the Twig template to generate a CSRF
251+
token and store it as a hidden field of the form:
252+
253+
.. code-block:: twig
254+
255+
<form action="{{ url('admin_post_delete', { id: post.id }) }}" method="post">
256+
{# the argument of csrf_token() is an arbitrary value used to generate the token #}
257+
<input type="hidden" name="token" value="{{ csrf_token('delete-item') }}" />
258+
259+
<button type="submit">Delete item</button>
260+
</form>
261+
262+
Then, get the value of the CSRF token in the controller action and use the
263+
:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::isCsrfTokenValid`
264+
to check its validity::
265+
266+
use Symfony\Component\HttpFoundation\Request;
267+
// ...
268+
269+
public function delete(Request $request)
270+
{
271+
$submittedToken = $request->request->get('token');
272+
273+
// 'delete-item' is the same value used in the template to generate the token
274+
if ($this->isCsrfTokenValid('delete-item', $submittedToken)) {
275+
// ... do something, like deleting an object
276+
}
277+
}
278+
279+
.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery
280+
.. _`Login CSRF attacks`: https://en.wikipedia.org/wiki/Cross-site_request_forgery#Forging_login_requests

0 commit comments

Comments
 (0)