CSRF state token does not match one provided FB PH

2020-01-28 05:48发布

问题:

My server logs show a "CSRF state token does not match one provided" error which seems to happen for almost every user. However, the users are created and/or authenticated and I am able to retrieve the user info. I am using a Linux server with Apache. I am also using the latest Facebook PHP SDK v.3.1.1 Can anyone tell me why this is happening and how to fix it?

回答1:

I had a similar issue last week, and tracked it down to the state field being overwritten by multiple calls to getLoginUrl(). Each time you call getLoginUrl(), a new state token is generated in the SDK and stored in the $_SESSION (it's just a random value), so if you call it twice and the user uses the first link to log in, the second call will have reset the SDK's internal state token, and you will get this error in your logs.

The SDK looks for the same state token in the URL coming back after Facebook authorizes the user and redirects them back to your site, and if it doesn't match it will log this error (here's a link to the source).



回答2:

Facebook SDK code has a bug when checking against tokens twice in the same handler.

I edited the getCode function of facebook.php like this:

protected function getCode() {
    if (!isset($_REQUEST['code']) || !isset($_REQUEST['state']) || $this->state === null) {
      return false;
    }
    if ($this->state === $_REQUEST['state']) {
        // CSRF state has done its job, so clear it
        $this->state = null;
        $this->clearPersistentData('state');
        return $_REQUEST['code'];
    }
    self::errorLog('CSRF state token does not match one provided.');

    return false;
}

to be more clear and does not state invalid token if called twice.

To be clear the function can be called twice on the same url handler if eg:

$facebook->getUser(); and then in the same handler $facebook->getLogoutUrl() then the getCode() is called twice thus resulting into and invalid error message



回答3:

Well, I've encountered this exact problem once, and I had a problem with the state & code parameters in the URL - my .htaccess file was not forwarding them.

I'm guessing you are having the same problem.

CSRF state token does not match one provided

Hope this helps



回答4:

To add a bit to chesles's answer, this problem can occur if you're playing with the session_start() - session_write_close() functions, as I did.

If there is no started session when you're requesting the loginUrl, you'll get this error.

Sidenote: Why bother stopping the session?

Scripts that use sessions stops each other, because they're waiting for the session array to be available to use.

Imagine that you have a popular application, with thousands of users, and have an action (a php script) where you post a picture. Something like this:

--starting session at the top of the script

--connecting to facebook

--creating the image

--sharing the image with the api call

--script end, session closes automatically

Doing this, the session will be used by the script for a long time for no reason. Be careful with such scripts, use something like this instead:

--starting session right before where you create the facebook object

--connecting to facebook

--closing session with session_write_close(), the session array's available, other scripts can load

--creating the image

--sharing the image with the api call /* It think this doesn't need a session. */

--script end, session already closed manually.

Cheers.



回答5:

One additional note - although it is not stated in the Facebook PHP API documentation, you have to have apache configured for PHP sessions for the login process to work. That turned out to be the problem we encountered when we were getting the "CSRF state token does not match one provided".

Make sure if you are using a server pool that you have it set up to use memcache for session information, otherwise apache will write the session information locally and if the next request doesn't go to the same server you will get the "CSRF state token does not match one provided".

This was one of those things that worked like a charm in a development environment (with one server) but failed in production.

We also had to reconfigure our CDN settings to make sure we were passing through the PHP Session cookie.



回答6:

I had the same issue. It´s easy. Don´t call

$fbLoginUrl = $facebook->getLoginUrl(...);

before

$fbUser = $facebook->getUser();

otherwise you will get "CSRF state token does not match one provided" error.



回答7:

I had the same problem in my local machine and the problem turned out to be that my hosts file was blocking communication with Verisign, so the URL Facebook tries to communicate with (http://crl.verisign.com/pca3.crl) never worked (state: 404).

Commenting out the various Verisign IP addresses from my hosts file did the trick!



回答8:

CSRF state and code are checked using local sessions, I bet you need to check your session.save_handler in your php.ini, and if it was working properly.



回答9:

if you use .htaccess mod rewrite redirects on your page, use the [QSA] (Query String Append) at the end of the lines to preserve the GET variables, or else you lost the $code variable, which is required to the facebook login