1
1
.. index ::
2
- single: Security ; CSRF Protection in the Login Form
2
+ single: CSRF ; CSRF protection
3
3
4
- Using CSRF Protection in the Login Form
5
- =======================================
4
+ How to Implement CSRF Protection
5
+ ================================
6
6
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 .
10
10
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.
12
14
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):
15
17
16
- Configuring CSRF Protection
17
- ---------------------------
18
+ .. code-block :: terminal
18
19
19
- First, make sure that the CSRF protection is enabled in the main configuration
20
- file:
20
+ $ composer require security-csrf form
21
21
22
- .. configuration-block ::
22
+ CSRF Protection in Symfony Forms
23
+ --------------------------------
23
24
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.
25
28
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 >`.
30
32
31
- .. code-block :: xml
33
+ .. _ form-csrf-customization :
32
34
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::
42
37
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;
47
41
48
- .. code-block :: php
42
+ class TaskType extends AbstractType
43
+ {
44
+ // ...
49
45
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.
54
86
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:
57
90
58
91
.. configuration-block ::
59
92
@@ -107,26 +140,12 @@ use the default provider available in the security component:
107
140
),
108
141
));
109
142
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
-
119
143
.. _csrf-login-template :
120
144
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 ``:
130
149
131
150
.. configuration-block ::
132
151
@@ -223,5 +242,39 @@ After this, you have protected your login form against CSRF attacks.
223
242
),
224
243
));
225
244
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