---
title: "Form protection tool"
manual: "TYPO3 Explained"
version: "13.4"
permalink: "https://docs.typo3.org/permalink/t3coreapi:csrf-backend@13.4"
source: "ApiOverview/FormProtection/Index.rst"
rendered: "2026-10-05T17:28:20+00:00"
---

# Form protection tool {#csrf-backend}

<!-- TODO: no Markdown rendering for "versionchanged" -->

Before TYPO3 v12.1, the FormProtectionFactory provided only static
methods to get the concrete form protection implementation. Since
TYPO3 v12.1, the FormProtectionFactory can be instantiated and
therefore injected into the constructor. The static methods are deprecated
and will be removed in TYPO3 v13.

The TYPO3 Core provides a generic way of protecting forms against cross-site
request forgery (CSRF).

> [!WARNING]
> **Attention**
>
> This **requires a logged-in user** whether in frontend or backend. CSRF
> protection is not supported for anonymous users. Without a logged-in user
> the token will always be `dummyToken`. See `77403` for details.

For each form in the backend/frontend (or link that changes some data), create a
token and insert it as a hidden form element. The name of the form element does
not matter; you only need it to get the form token for verifying it.

## Examples {#csrf-examples}

**EXT:my_extension/Classes/Controller/FormProtectionExample.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;

final class FormProtectionExample
{
  public function __construct(
    private readonly FormProtectionFactory $formProtectionFactory,
  ) {}

  public function handleRequest(ServerRequestInterface $request): ResponseInterface
  {
    $formProtection = $this->formProtectionFactory->createFromRequest($request);

    $formToken = $formProtection->generateToken('BE user setup', 'edit');

    $content = '<input type="hidden" name="formToken" value="' . $formToken . '">';

    // ... some more logic ...
  }
}

```

The three parameters of the `generateToken()` method:

-   `$formName`
-   `$action` (optional)
-   `$formInstanceName` (optional)

can be arbitrary strings, but they should make the form token as specific as
possible. For different forms (for example, BE user setup and editing a
`tt_content` record) or different records (with different UIDs) from the
same table, those values should be different.

For editing a `tt_content` record, the call could look like this:

**EXT:my_extension/Classes/Controller/FormProtectionExample.php (Excerpt)**

```php
$formToken = $formProtection->generateToken('tt_content', 'edit', (string)$uid);
```

When processing the data that has been submitted by the form, you can check that
the form token is valid like this:

**EXT:my_extension/Classes/Controller/FormProtectionExample.php (Excerpt)**

```php
if ($dataHasBeenSubmitted &&
    $formProtection->validateToken(
        $request->getParsedBody()['formToken'] ?? '',
        'BE user setup',
        'edit'
    ) ) {
    // process the data
} else {
    // No need to do anything here, as the backend form protection will
    // create a flash message for an invalid token
}
```

As it is recommended to use `FormProtectionFactory->createForRequest()`
to auto-detect which type is needed, one can also create a specific type
directly:

**EXT:my_extension/Classes/Controller/FormProtectionExample.php (Excerpt)**

```php
// For backend
$formProtection = $this->formProtectionFactory->createFromType('backend');

// For frontend
$formProtection = $this->formProtectionFactory->createFromType('frontend');
```
