Skip to content

Commit

Permalink
Fix csrf token validation after submit (#285)
Browse files Browse the repository at this point in the history
* Fix csrf token validation after submit

* Refractor static form csrf token controller

* Add UPGRADE file
  • Loading branch information
alexander-schranz committed Apr 12, 2021
1 parent 1b03bc7 commit 5e6f116
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 9 deletions.
7 changes: 6 additions & 1 deletion Controller/FormWebsiteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Sulu\Bundle\FormBundle\Controller;

use Sulu\Bundle\FormBundle\Configuration\FormConfigurationFactory;
use Sulu\Bundle\FormBundle\Csrf\DisabledCsrfTokenManager;
use Sulu\Bundle\FormBundle\Form\HandlerInterface;
use Sulu\Bundle\FormBundle\Form\Type\AbstractType;
use Sulu\Bundle\WebsiteBundle\Controller\DefaultController;
Expand All @@ -23,6 +24,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
* @deprecated static forms are deprecated and should not longer be used
Expand Down Expand Up @@ -53,6 +55,7 @@ public static function getSubscribedServices()
$subscribesServices['form.registry'] = FormRegistryInterface::class;
$subscribesServices['sulu_form.configuration.form_configuration_factory'] = FormConfigurationFactory::class;
$subscribesServices['sulu_form.handler'] = HandlerInterface::class;
$subscribesServices['security.csrf.token_manager'] = CsrfTokenManagerInterface::class;

return $subscribesServices;
}
Expand All @@ -74,7 +77,9 @@ public function formAction(Request $request, StructureInterface $structure, bool
$type = $this->get('form.registry')->getType($typeClass)->getInnerType();
$type->setAttributes($attributes);

$this->form = $this->get('form.factory')->create($typeClass);
$this->form = $this->get('form.factory')->create($typeClass, [], [
'csrf_token_manager' => new DisabledCsrfTokenManager($this->get('security.csrf.token_manager')),
]);
$this->form->handleRequest($request);

if ($this->form->isSubmitted()
Expand Down
16 changes: 13 additions & 3 deletions Csrf/DisabledCsrfTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,29 @@

class DisabledCsrfTokenManager implements CsrfTokenManagerInterface
{
/**
* @var CsrfTokenManagerInterface
*/
private $csrfTokenManager;

public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
{
$this->csrfTokenManager = $csrfTokenManager;
}

public function refreshToken(string $tokenId)
{
throw new \RuntimeException('Should not be called');
return $this->csrfTokenManager->refreshToken($tokenId);
}

public function removeToken(string $tokenId)
{
throw new \RuntimeException('Should not be called');
return $this->csrfTokenManager->removeToken($tokenId);
}

public function isTokenValid(CsrfToken $token)
{
throw new \RuntimeException('Should not be called');
return $this->csrfTokenManager->isTokenValid($token);
}

public function getToken(string $tokenId)
Expand Down
12 changes: 11 additions & 1 deletion Form/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Sulu\Bundle\FormBundle\Form;

use Sulu\Bundle\FormBundle\Csrf\DisabledCsrfTokenManager;
use Sulu\Bundle\FormBundle\Dynamic\Checksum;
use Sulu\Bundle\FormBundle\Dynamic\FormFieldTypePool;
use Sulu\Bundle\FormBundle\Entity\Dynamic;
Expand All @@ -23,6 +24,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
* Builds a dynamic form.
Expand Down Expand Up @@ -64,20 +66,27 @@ class Builder implements BuilderInterface
*/
protected $checksum;

/**
* @var CsrfTokenManagerInterface
*/
private $csrfTokenManager;

public function __construct(
RequestStack $requestStack,
FormFieldTypePool $formFieldTypePool,
TitleProviderPoolInterface $titleProviderPool,
FormRepository $formRepository,
FormFactory $formFactory,
Checksum $checksum
Checksum $checksum,
CsrfTokenManagerInterface $csrfTokenManager
) {
$this->requestStack = $requestStack;
$this->formFieldTypePool = $formFieldTypePool;
$this->titleProviderPool = $titleProviderPool;
$this->formRepository = $formRepository;
$this->formFactory = $formFactory;
$this->checksum = $checksum;
$this->csrfTokenManager = $csrfTokenManager;
}

/**
Expand Down Expand Up @@ -212,6 +221,7 @@ private function createForm(string $name, string $type, string $typeId, string $
'csrf_protection' => $csrfTokenProtection,
'name' => $name,
'block_name' => 'dynamic_' . $name,
'csrf_token_manager' => new DisabledCsrfTokenManager($this->csrfTokenManager),
]
);
}
Expand Down
2 changes: 0 additions & 2 deletions Form/Type/AbstractType.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

namespace Sulu\Bundle\FormBundle\Form\Type;

use Sulu\Bundle\FormBundle\Csrf\DisabledCsrfTokenManager;
use Symfony\Component\Form\AbstractType as SymfonyAbstractType;
use Symfony\Component\Form\Util\StringUtil;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand Down Expand Up @@ -61,7 +60,6 @@ public function configureOptions(OptionsResolver $resolver)
if ($this->csrfProtection) {
$defaults['csrf_field_name'] = $this->csrfFieldName;
$defaults['intention'] = $this->getDefaultIntention();
$defaults['csrf_token_manager'] = new DisabledCsrfTokenManager();
}

if ($this->dataClass) {
Expand Down
2 changes: 0 additions & 2 deletions Form/Type/DynamicFormType.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

namespace Sulu\Bundle\FormBundle\Form\Type;

use Sulu\Bundle\FormBundle\Csrf\DisabledCsrfTokenManager;
use Sulu\Bundle\FormBundle\Dynamic\Checksum;
use Sulu\Bundle\FormBundle\Dynamic\FormFieldTypePool;
use Sulu\Bundle\FormBundle\Entity\Dynamic;
Expand Down Expand Up @@ -193,7 +192,6 @@ public function configureOptions(OptionsResolver $resolver)

$defaults['csrf_protection'] = true;
$defaults['csrf_field_name'] = '_token';
$defaults['csrf_token_manager'] = new DisabledCsrfTokenManager();
$defaults['data_class'] = Dynamic::class;

$resolver->setDefaults($defaults);
Expand Down
1 change: 1 addition & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
<argument type="service" id="sulu_form.repository.form" />
<argument type="service" id="form.factory" />
<argument type="service" id="sulu_form.checksum" />
<argument type="service" id="security.csrf.token_manager"/>
</service>

<!-- Dynamic Form Type -->
Expand Down
7 changes: 7 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Upgrade

## 2.1.1

### Builder constructor changed

The `Builder` service of the SuluFormBundle requires now the `security.csrf.token_manager` service to be injected
this was required to solve caching problems on pages using forms.

## 2.1.0

### Database
Expand Down

0 comments on commit 5e6f116

Please sign in to comment.