I am trying to use a stored access token, but after 2 hours I get the error below from the chart API. I wrote a code to send to a user on Facebook in order to get a new code that can be exchanged for an access token that works just fine, except that this happens with every subsequent page request. Facebook continues to strip my access token with an error below, even though the access token is being returned by their server.
Error validating access token: Session has expired at unix time 1338300000. The current unix time is 1338369365.
Below is an example of a complete test page. Omitting keys for obvious reasons. Click on the page, log in, and then leave it for a few hours and click on the page again (you will get a redirect to facebook and back with the code in the URL), reload the page and it will continue to redirect to facebook and back, an event although I tell him to use the access token that he just returned for the specified code.
<?php require 'facebook.php'; $app_id = APP_ID; $app_secret = APP_SERCRET; $my_url = URL; $facebook = new Facebook(array( 'appId' => $app_id, 'secret' => $app_secret )); // known valid access token stored in a database $access_token = isset($_COOKIE["FB_LONG_AC_TOKEN"]) ? $_COOKIE["FB_LONG_AC_TOKEN"] : false; $code = $_REQUEST["code"]; // If we get a code, it means that we have re-authed the user //and can get a valid access_token. if (isset($code)) { $token_url="https://graph.facebook.com/oauth/access_token?client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url) . "&client_secret=" . $app_secret . "&code=" . $code . "&display=popup"; $response = file_get_contents($token_url); $params = null; parse_str($response, $params); $access_token = $params['access_token']; } // Attempt to query the graph: $graph_url = "https://graph.facebook.com/me?" . "access_token=" . $access_token; $response = curl_get_file_contents($graph_url); $decoded_response = json_decode($response); //Check for errors if ($decoded_response->error) { // check to see if this is an oAuth error: if ($decoded_response->error->type== "OAuthException") { // Retrieving a valid access token. $dialog_url= "https://www.facebook.com/dialog/oauth?" . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url); echo("<script> top.location.href='" . $dialog_url . "'</script>"); } else { echo "other error has happened"; } } else { // success echo("Success: ".$decoded_response->name."<br />"); echo($access_token."<br />"); // Attempt to convert access token to longlife token if we don't have one stored. if (!isset($_COOKIE["FB_LONG_AC_TOKEN"])) { // don't have long life token, so let get one. $ch = curl_init("https://graph.facebook.com/oauth/access_token?client_id=".$app_id."&client_secret=".$app_secret."&grant_type=fb_exchange_token&fb_exchange_token=".$access_token); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $data = curl_exec($ch); curl_close($ch); $params = null; parse_str($data, $params); if (isset($params["access_token"])) { $access_token = $params["access_token"]; echo("Got long life token.<br />"); setcookie("FB_LONG_AC_TOKEN", $access_token, time() + (3600 * 24 * 60), "/"); } } else { echo("Have long life token already.<br />"); } } if ($access_token) { $facebook->setAccessToken($access_token); // See if there is a user from a cookie $user = $facebook->getUser(); if ($user) { try { // Proceed knowing you have a logged in user who authenticated. $user_profile = $facebook->api('/me'); } catch (FacebookApiException $e) { echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>'; $user = null; } } } // note this wrapper function exists in order to circumvent PHP's //strict obeying of HTTP error codes. In this case, Facebook //returns error code 400 which PHP obeys and wipes out //the response. function curl_get_file_contents($URL) { $c = curl_init(); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_URL, $URL); $contents = curl_exec($c); $err = curl_getinfo($c,CURLINFO_HTTP_CODE); curl_close($c); if ($contents) return $contents; else return FALSE; } ?> <!doctype html> <html xmlns:fb="http://www.facebook.com/2008/fbml"> <head> <title>Facebook Auth</title> </head> <body> <?php if ($user) { ?> Your user profile is <pre> <?php print htmlspecialchars(print_r($user_profile, true)) ?> </pre> <?php } else { ?> <fb:login-button></fb:login-button> <?php } ?> <div id="fb-root"></div> <script> window.fbAsyncInit = function () { FB.init({ appId: <?php echo($app_id); ?>, cookie: true, // enable cookies to allow the server to access the session oauth: true, // enable OAuth 2.0 xfbml: true // parse XFBML }); FB.getLoginStatus(function (res) { console.log(res.status); }); }; (function(d){ var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;} js = d.createElement('script'); js.id = id; js.async = true; js.src = "//connect.facebook.net/en_US/all.js"; d.getElementsByTagName('head')[0].appendChild(js); }(document)); </script> </body> </html>
What am I doing wrong? or is it a problem with facebook?
UPDATE:
I updated my code to follow the stream sent by @cpilko, but I still have the same problem. I can get in and out just fine. However, if after a few hours I go to the test page, I will say that the next day I will receive an expired exception with the provided access token for a long service life (FB JS SDK considers that I am connected, but the server did not do this), I I refresh the page and I show that both the server and the FB JS SDK are logged in, and the long token that I get from facebook matches the one I used in the original (saved in my cookies). I do not understand why I can not use a long-term token for the first time. Updated code below.
<?php require 'facebook.php'; $app_id = "XXXXXXXXXXXXX"; $app_secret = "XXXXXXXXXXXXXXXXXXXX"; $my_url = "http://swan.magicseaweed.local/facebook/"; $facebook = new Facebook(array( 'appId' => $app_id, 'secret' => $app_secret )); $valid_user = false; var_dump($_COOKIE); echo("<br />"); if (isset($_COOKIE["FB_LONG_AC_TOKEN"])) { <!doctype html> <html xmlns:fb="http://www.facebook.com/2008/fbml"> <head> <title>Facebook Auth</title> </head> <body> <?php if ($user) { ?> Your user profile is <pre> <?php print htmlspecialchars(print_r($user_profile, true)) ?> </pre> <?php } else { ?> <fb:login-button></fb:login-button> <?php } ?> <div id="fb-root"></div> <script> window.fbAsyncInit = function () { FB.init({ appId: <?php echo($app_id); ?>, cookie: true, // enable cookies to allow the server to access the session oauth: true, // enable OAuth 2.0 xfbml: true // parse XFBML }); FB.getLoginStatus(function (res) { console.log(res.status); }); }; (function(d){ var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;} js = d.createElement('script'); js.id = id; js.async = true; js.src = "//connect.facebook.net/en_US/all.js"; d.getElementsByTagName('head')[0].appendChild(js); }(document)); </script> </body> </html>