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.

CSRF validation does not work on remote server

Hello,

I have some forms on my site that also have csrf validation attached with the standard $this->security->getTokenKey() and $this->getToken()

In my controller I check the token as usual:

$this->security->checkToken()

THe problem is though that the CSRF validation works perfectly on my local machine (running XAMPP) but doesn't on my remove server (CentOS with Apache/PHP/MariaDB).

I'm running on PHP5.5 and using PhalconPHP version 1.3.4.

What could it be caused by?



58.2k

HI

This error can occur when the folder session PHP haven't permissons , refer to it https://github.com/puphpet/puphpet/issues/274

edited Feb '15

Hi,

Sorry on the late reply. I checked my php.ini to find out what my session.save_path is and it wasn't set (PHP\s default is nothing). So i set it to /var/lib/php/session based on the issue from Github and then chowned it to root:apache. This however doesn't seem to have been the issue as for some reason the validation still fails.

After searching through the forum earlier, I did notice that some people noted a wierd csrf behaviour with the absence of a favicon.ico. In my local server, my application picks up xampp\s favicon from the htdocs directory whereas my remote server doesn't have any favicon. Could this be the same case here?

I did try adding this to my project_root/.htaccess and my project_root/public/.htaccess:

RedirectMatch 204 /robots.txt
RedirectMatch 204 /favicon.ico

But it doesn't seem to have worked. DId I add this correctly? Or could it be caused by something else still?

Updated: It does seem to be a session issue no doubt. I tested by doing

var_dump($this->security->getSessionToken());

And it returned NULL. Doing session_save_path() returns me /var/lib/php/session as I've set it previously. I also checked if it is_writable and it returned me true.

Updated #2: I set the session.save_path to /tmp and now getSessionToken() is no longer NULL however the CSRF validation still fails.



2.1k
Accepted
answer
edited Feb '15

currently there are some issues when you get double calls, i know chrome had that issue, one good workaround is to use a session one time csrf key, basically it will always be the same key during the session unless you explictly change it.

class Security extends \Phalcon\Security
{
    public function getTokenKey($numberBytes = 13)
    {
        $key = '$PHALCON/CSRF/KEY$';

        $tokenKey = \Phalcon\DI::getDefault()->get('session')->get($key);

        if ($tokenKey)
        {
            return $tokenKey;
        }

        return parent::getTokenKey($numberBytes);
    }   

    public function getToken($numberBytes = 32)
    {
        $key = '$PHALCON/CSRF$';

        $token = \Phalcon\DI::getDefault()->get('session')->get($key);

        if ($token)
        {
            return $token;
        }

        return parent::getToken($numberBytes);
    } 

    public function changeToken($numberBytes = 32)
    {
        return parent::getToken($numberBytes);
    }

}

You can set the session to any directory, if you are on shared hosting, best to put it in a local folder instead of the default.

// You may have a better location, I plan to put this on my shared hosting account
$di->setShared('session', function() {
            session_save_path(__DIR__ . '/../apps/data/sessions/');
            $session = new Phalcon\Session\Adapter\Files([
                'uniqueId' => 'eh_',
            ]);
            $session->start();
            return $session;
        });

A huge thanks. your solution did the trick :). I don't know why the default way doesn't work on my remote server but I'm happy that this finally resolved it.