Skip to content

Commit 7c6e342

Browse files
authored
Merge pull request #3 from dotkernel/issue-2
Issue #2: Added `CSRF` documentation
2 parents 83540d0 + b56570c commit 7c6e342

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

docs/book/v5/core-features/csrf.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# CSRF protection in forms
2+
3+
A Cross-Site Request Forgery (CSRF) attack is a type of security vulnerability that tricks a user into performing
4+
actions on a web application in which they are authenticated, without their knowledge or consent.
5+
6+
Web applications can protect users against these types of attacks by implementing CSRF tokens in their forms which are
7+
known only to the application that generated them and must be included when submitting forms. With each visit, a new
8+
CSRF token is added to the form so tokens are not reusable between forms. Missing to provide a valid CSRF token will
9+
result in a form validation error.
10+
11+
## Implement CSRF protection
12+
13+
Implementing CSRF protection requires three steps:
14+
15+
- create new field using [laminas/laminas-form](https://github.com/laminas/laminas-form)'s [CSRF](https://github.com/laminas/laminas-form/blob/3.21.x/src/Element/Csrf.php) element
16+
- validate new field using [laminas/laminas-session](https://github.com/laminas/laminas-session)'s
17+
[CSRF](https://github.com/laminas/laminas-session/blob/2.22.x/src/Validator/Csrf.php) validator
18+
- render field using [laminas/laminas-form](https://github.com/laminas/laminas-form)'s [FormElement](https://github.com/laminas/laminas-form/blob/3.21.x/src/View/Helper/FormElement.php) helper
19+
20+
### Create field
21+
22+
Open the form's PHP class and append the following code to the method that initializes the fields (usually `init`):
23+
24+
```php
25+
$this->add(new \Laminas\Form\Element\Csrf('exampleCsrf', [
26+
'csrf_options' => [
27+
'timeout' => 3600,
28+
'session' => new \Laminas\Session\Container(),
29+
],
30+
]));
31+
```
32+
33+
where `exampleCsrf` should be a suggestive name that describes the purpose of the field (example: `forgotPasswordCsrf`).
34+
35+
### Validate field
36+
37+
Open the InputFilter that validates the form fields and append the following code to the method that initializes the
38+
fields (usually `init`):
39+
40+
```php
41+
$csrf = new \Laminas\InputFilter\Input('exampleCsrf');
42+
$csrf->setRequired(true);
43+
$csrf->getFilterChain()
44+
->attachByName(\Laminas\Filter\StringTrim::class)
45+
->attachByName(\Laminas\Filter\StripTags::class);
46+
$csrf->getValidatorChain()
47+
->attachByName(\Laminas\Validator\NotEmpty::class, [
48+
'message' => '<b>CSRF</b> is required and cannot be empty',
49+
], true)
50+
->attachByName(\Laminas\Session\Validator\Csrf::class, [
51+
'name' => 'exampleCsrf',
52+
'message' => '<b>CSRF</b> is invalid',
53+
'session' => new \Laminas\Session\Container(),
54+
], true);
55+
$this->add($csrf);
56+
```
57+
58+
where `exampleCsrf` must match the CSRF field's name in the form.
59+
60+
> Don't forget to modify both occurrences in this file.
61+
62+
> Make sure that you validate the form using its `isValid` method in the handler/controller where it is submitted.
63+
64+
### Render field
65+
66+
Open the template that renders your form and add the following code somewhere between the form's opening and closing
67+
tags:
68+
69+
```text
70+
{{ formElement(form.get('exampleCsrf')) }}
71+
```
72+
73+
## Test the implementation
74+
75+
Access your form from the browser and view its source. You should see a new hidden field, called `exampleCsrf` (or
76+
however you named it). After filling out the form, submitting it should work as before.
77+
78+
In order to make sure that the new CSRF field works as expected, you can inspect the form using your browser's
79+
`Developer tools` and modify its value in any way. Submitting a filled out form should result in a validation error:
80+
81+
> **CSRF** is required and cannot be empty
82+
83+
### Timeout
84+
85+
Note the `timeout` option in your PHP form's `exampleCsrf` field, with its default value set to **3600**. This
86+
represents the value in seconds for how long the token is valid. Submitting a form that has been rendered for longer
87+
than this value will result in a validation error:
88+
89+
> **CSRF** is invalid
90+
91+
You can modify the value of `timeout` in each form, but the default value should work in most cases.

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ nav:
1818
- "Doctrine ORM": v5/installation/doctrine-orm.md
1919
- "Manage Geolite2": v5/installation/manage-geolite2.md
2020
- "Test the Installation": v5/installation/test-the-installation.md
21+
- Core Features:
22+
- "CSRF": v5/core-features/csrf.md
2123
site_name: admin
2224
site_description: "DotKernel Admin"
2325
repo_url: "https://github.com/dotkernel/admin"

0 commit comments

Comments
 (0)