Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check whether the supplied CSRF token is invalid in Symfony2?

I have created a Symfony2 form and bound it to the Request. I need to explicitly ensure whether the CSRF token is valid/invalid before proceeding with the rest of the form.

$form['_token']->isValid() throws OutOfBoundsException with message "Child _token does not exist."

I can still verify that the rendered form contains _token field. In case that CSRF value is invalid, $form->isValid() returns false.

What am I missing here?


Update 1:

Controller (partial):

private function buildTestForm() {
    $form = $this->createFormBuilder()
            ->add('name','text')
            ->getForm();
    return $form;
}

/**
 * @Route("/test/show_form", name="test.form.show")
 * @Method("GET")
 */
public function showFormTest()
{
    $form = $this->buildTestForm();
    return $this->render('TestBundle::form_test.html.twig', array('form' => $form->createView()));
}

/**
 * @Route("/test/submit_form", name="test.form.submit")
 * @Method("POST")
 */
public function formTest()
{
    $form = $this->buildTestForm();
    $form->bind($this->getRequest());
    if ($form['_token']->isValid()) {
        return new Response('_token is valid');
    } else {
        return new Response('_token is invalid');
    }
}

Template

{# Twig template #}
<form action="{{ path('test.form.submit') }}" method="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}
    <input type="submit" name="go" value="Test Form" />
</form>
like image 757
Ville Mattila Avatar asked Feb 23 '13 19:02

Ville Mattila


People also ask

How do I know if my CSRF token is working?

A couple of ways you can test it: Open the developer tools in your browser find the input element for the CSRF token and edit the token value. Trigger a POST submission. This should cause an error, HTTP status 403 typically.

Where can I find the CSRF token?

In addition to this, the CSRF token should be stored on the server-side application, which verifies every request that requires validation. The server-side application should ensure that valid requests include a token matching the value stored during the user's active session.


2 Answers

Another way (if you prefer DI) to validate token outside of controller (e.g. in listener):

/** @var Symfony\Component\Security\Csrf\CsrfTokenManagerInterface */
private $csrfTokenManager;

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

public function isValid(): bool
{
    return $this->csrfTokenManager->isTokenValid(
            new CsrfToken('authenticate', $request->getRequest()->headers->get('X-CSRF-TOKEN'))
        );
}
like image 114
Victor Fedorenko Avatar answered Oct 08 '22 15:10

Victor Fedorenko


In addition to artworkad, you can specify an intention:

Twig:

<form method="post">
    <input type="text" name="form_name[field]" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('form_name', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));

Or not:

Twig:

<form method="post">
    <input type="text" name="field" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));
like image 27
p-bizouard Avatar answered Oct 08 '22 14:10

p-bizouard