Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

CSRF not working

I can't seem to get the CSRF to work. I have a custom form, and in the form I add the hidden input for the CSRF:

private function csrfField()
{
    $csrf = new Hidden('csrf', [
        'value' => $this->security->getToken()
    ]);

    $csrf->addValidator(new Identical(array(
        'value' => $this->security->getSessionToken(),
        'message' => 'Failed to create account. Try again.'
    )));

    $this->add($csrf);
}

When I check the source, the CSRF token is present. But, when I submit the form, and check if the token is valid it always comes back as false. Here is the method from my controller that's hit when the form is submitted.

public function createAction()
{
    $form = new CreateSnapForm();
    $form->bind($this->request->getPost(), new CreateSnapPostData());

    if ($this->security->checkToken()) {
        $this->flash->error($form->getMessages()[0]);
        $this->dispatcher->forward([ 'action' => 'index' ]);
        return;
    }

    ...

It always fails. What am I doing wrong here? If you need more info, feel free to ask

Is this an issue with Phalcon or are we doing it wrong?

edited May '15

I notice that in the source it's outputted as:

<input type="hidden" id="csrf" name="csrf" value="adf7f2db81cc14177a63d804dfd2e766" />

I thought the name was meant to be the key and the value as the token? I'm looking through the Phalcon source and the Security module at the moment to see what could be the issue.



3.4k
Accepted
answer
edited May '15

Solved.

I removed adding the csrf field from the Form (which is a bit unfortunate, as I like to keep these things grouped together), and instead generate the csrf field in the view:

  <input type="hidden" name="<?= $this->security->getTokenKey() ?>" value="<?= $this->security->getToken() ?>">

In the controller I can now use:

 if (!$this->security->checkToken()) {
        $this->flash->error('Your session expired. Try that one again.');
        $this->dispatcher->forward([ 'action' => 'index' ]);
        return;
    }

It now works :) thank you to Gevox on IRC for the help.