We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Problem with CSRF

I've done this part of the docs https://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.8k
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.8k
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()