CSRF-Token invalid when re-submitting a form (Phalcon 2.0)

Hi,

I'm facing a CSRF issue: I can only submit the form once, but if I try to submit the form again (e.g. when I forgot to fill field that is required) it won't work and I get 'CSRF-token validation failed'. The same code worked using Phalcon 1.x. Any ideas how to fix this behavior?

MyForm.php

<?php
class MyForm extends Form
{
    public function initialize()
    {
        $csrf  = new Hidden('csrf');
        // ... some other fields

        $csrf->addValidator(new Identical(array(
            'value'   => $this->security->getSessionToken(),
            'message' => 'CSRF-token validation failed'
        )));

        $this->add($csrf);

    }

}

IndexController.php

class IndexController extends Controller
{
    public function registerAction()
    {
        $form = new MyForm();

        if ($this->request->isPost())
        {
            // Validate form against post data
            if (!$form->isValid($this->request->getPost()))
            {
                // Display error messages
                foreach ($form->getMessages() as $message)
                {
                    $this->flash->error($message);

                }

            }
            else
            {
                // ... assign submitted values to model and redirect

            }
        }

        // Assign form to view
        $this->view->form = $form;

    }

}


4.0k

Similar post https://forum.phalconphp.com/discussion/6938/phalcon-csrf-in-self-submit-form. Maybe it will help. If not - paste your html template.

Similar post https://forum.phalconphp.com/discussion/6938/phalcon-csrf-in-self-submit-form. Maybe it will help. If not - paste your html template.

register.volt

<!-- Some more HTML… -->
{{ form.render('csrf', ['value': security.getToken()]) }}
<!-- Some more HTML… -->


4.0k

Try modify your code by this comment

register.volt

        {{ form.render('csrf', ['name': this.security.getTokenKey(), 'value': this.security.getToken()]) }}

MyForm.php

        // change from 
        $csrf->addValidator(new Identical(array(
            'value'   => $this->security->getSessionToken(),
            'message' => 'CSRF-token validation failed'
        )));
        //change to
        $csrf->addValidator(new Identical(array(
            $this->security->checkToken() => 1,
            'message' => 'CSRF-token validation failed'
        )));
edited Jun '15

Try modify your code by this comment

This will result in a non-working CSRF-check as commented here and therefore isn't a safe solution.



4.0k
edited Jun '15

Sorry. My bad.

I found one solution.

register.volt

{{ form.render('csrf') }}

MyForm.php

class MyForm extends \Phalcon\Forms\Form
{
    private $lastCsrfValue = null;

    public function getCsrf()
    {
        return ($this->lastCsrfValue !== null) ? $this->lastCsrfValue : $this->lastCsrfValue = $this->security->getToken();
    }

    public function initialize()
    {
        $csrf  = new \Phalcon\Forms\Element\Hidden('csrf');
        // ... some other fields

        $csrf->addValidator(new \Phalcon\Validation\Validator\Identical(array(
            'value'   => $this->security->getSessionToken(),
            'message' => 'CSRF-token validation failed'
        )));

        $this->add($csrf);

    }
}