We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

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.

Problem with CSRF

I've done this part of the docs http://docs.phalcon.io/en/latest/reference/security.html#cross-site-request-forgery-csrf-protection . To test it, I modified the input name, but the server also returns true. Did I misunderstand something?

User input:

{{ text_field(this.security.getTokenKey()) }}

Controller:

    if ($this->request->isPost())
        {
            echo '<pre>';
            var_dump($this->security->checkToken());
            die();
        }

What do you mean by 'modified the input name'? Check output html, maybe volt-engine automatically adds it (i dont know for sure, because not using it).


    <input type="hidden" name="key" value="value" />
  • key – result of $this->security->getTokenKey()
  • value – result of $this->security->getToken();


33.7k
edited Nov '14

I mean modifying the name attribute. And yes, Volt automatically sets id and name equal to the first param in the function.

But I saw a hidden in your INPUT and know I'm confused: the token is only once in the form, or is for each INPUT that is going to be a POST value?



3.3k
Accepted
answer
edited Nov '14

Attribute hidden not necessary, but i don't think, that your users need to see this field, it will confuse them. In Phalcon, as far as i know, you can create only one CSRF-token per-page. I dont understand why you need to change name-attribute of input, but, in .phtml templates i do like this:


    <!-- source -->
    <input type="hidden" name="<? echo $this->security->getTokenKey(); ?>" value="<? echo $this->security->getToken(); ?>" />

    <!-- In result we will have this -->
    <input type="hidden" name="iQrC2JVWQZsyoN6N" value="20169bf9cfc1d92d349a14be1f8c674d">

Then, in php you will check token like this


    if ($this->request->isPost()) {
        if ($this->request->checkToken()) {
            // Okay, this is POST-method, and CSRF-token is fine
        }
    }

Also, be advised, that security token will be generated each time you call $this->security->getTokenKey()

If you need to implement Ajax request, then you probably need to store those key & value else where.


    <form data-key="token-key-goes-here" data-value="token-value-goes-here">

    <script>
        // Add values to 
        var data = {
            key: $('form').attr('data-key'),
            value: $('form').attr('data-value),
        };

        // then you add form's data 
        $.ajax('url', data)
    </script>

Then, in php, call $this->security->checkToken() with arguments of key & value like this


    $this->security->checkToken($this->request->getPost('key'), $this->request->getPost('value'));


33.7k
edited Nov '14

Ahhh, now it's clear, I thinked that the token was for each INPUT, to ensure that new ones weren't created in the client to be sended with malicious data. Thanks.

EDIT: is getToken(), not getTokenValue()