4

I know there are tons of post on stackoverflow about the issue on "CSRF state token does not match one provided." However, I tried and doesn't seem to solve the issue. Can you please take a look at my code below? Please tell me what you think and how to solve the problem. I have already updated to latest PHP SDK version.

<?
require_once ('src/facebook.php');
require_once ('src/fbconfig.php');

//Facebook Authentication part
$user_id = $facebook->getUser();
$loginUrl = $facebook->getLoginUrl(array(
    'scope' => 'publish_stream')
);

if ($user_id) {
    $_SESSION['user_id'] = $user_id;
    echo "<script>top.location.href = 'https://www.example.com/app-folder/welcome'</script>"; 
    exit;
} 
?>
    .
    .
<body>
<?php echo '<a href="'.$loginUrl.'" target="_top">Please login</a>'; ?>
    .
    .
</body>
Nick
  • 315
  • 2
  • 9
  • 17

4 Answers4

11

getLoginUrl() generates a new token. If your user is already logged in (with $user_id = $facebook->getUser()), you'll end up with 2 tokens.

Don't ask for the $loginUrl if the user is authenticated already.

$user_id = $facebook->getUser();

if ($user_id) {
    $_SESSION['user_id'] = $user_id;
    echo "<script>top.location.href = 'https://www.example.com/app-folder/welcome'</script>"; 
    exit;
} else {
    $loginUrl = $facebook->getLoginUrl(array(
        'scope' => 'publish_stream')
    );
}

?>

Tchoupi
  • 14,560
  • 5
  • 37
  • 71
  • Yeah my code above didnt ask the user to login again if they authenticate already. If there is user id then they will lead to another page, while if no user id they will be asked to authenticate. – Nick Aug 15 '12 at 14:44
  • i think the difference between my code and yours is i separate it with html code if there is no user id – Nick Aug 15 '12 at 14:46
  • @Nick I'm not sure I understand. Have you tried my code? Does it work? – Tchoupi Aug 15 '12 at 14:47
  • Sorry not yet. I'll try it out. What i meant is that, please correct me if i'm wrong, it won't make different to include getloginurl() before or after if ($user_id) because the actual work of authentication would be at when echo $login_url or asking user to login. – Nick Aug 15 '12 at 14:57
  • As said in the link I sent you: "I had a similar issue last week, and tracked it down to the state field being overwritten by multiple calls to getLoginUrl()". In you code you call `getLoginUrl()` every time before checking if `$user_id` is `false` or not. In my code I make sure that `getLoginUrl()` is called *only* if `$user_id` is false, menaing if the user is not logged in. – Tchoupi Aug 15 '12 at 15:02
  • ok. I'm trying the code. I'll update you soon. – Nick Aug 15 '12 at 15:07
  • Hi, the code didn't work out. I still get the error in the my error log. Any idea? – Nick Aug 16 '12 at 12:13
  • 2
    Would it be possible that the getuser() sometimes return 0 or null, while the user already logged in? This would lead the user to log in again? – Nick Aug 16 '12 at 12:14
  • @Mathieu Imbert : I also have the very same issue. `getUser()` sometimes returns null even if the user is already logged in. I tried to logout the user and then ask him to login again but it still has the same problem! This error is only resolved if the user restarts his browser. Any clues? – Haywire Mar 28 '13 at 07:57
0

I had to do the following:

  1. Use PHP SDK's getLoginUrl only on the first page (ie. login/index) and remove it from all the other pages.
  2. Use FB.getLoginStatus() from the Javascript SDK and fallback to the FB.login() or a redirect to the login/index page
  3. Check the FB.getLoginStatus() before you attempt anything that might require a valid access_token

I'm convinced that the main issue was the fact that I called getLoginUrl on every single page.

Since I made these changes I only get the "CSRF state token" error in the logs when robots hit my pages.

Charley P.
  • 184
  • 1
  • 13
0

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.

-3

work-around :
go to base_facebook.php

look for the protected function getCode() this is the problem.
the $this->state variable doesn't stay saved for off-site navigation (natural)

replace this:

if ($this->state !== null &&
isset($_REQUEST['state']) &&
$this->state === $_REQUEST['state']) {

with this:

if ($_REQUEST['state'] != '' && $_REQUEST['code'] != '') {

And it's going to work just good

G@bri3l

Barnee
  • 3,212
  • 8
  • 41
  • 53
Pian0_M4n
  • 2,505
  • 31
  • 35
  • 1
    That way you are just disabling CSRF protection completely … so I would not consider this a “solution” to the problem. – CBroe Mar 11 '13 at 13:17
  • Will when you choose a php login solution, you go to facebook.com and then back. How do you think $this witch is defined before changing domain would remain != '' after going to different URL ? – Pian0_M4n Mar 11 '13 at 18:16