Facebook SDK access tokens and ajax Facebook SDK access tokens and ajax ajax ajax

Facebook SDK access tokens and ajax


Here is the actual code that works with explanations to what had to change below:

fb-callback.php

<?phprequire_once("config.php");try {  $accessToken = $helper->getAccessToken();} catch(Facebook\Exceptions\FacebookResponseException $e) {  // When Graph returns an error  echo __LINE__ . ' Access Token: Graph returned an error: ' . $e->getMessage();  exit;} catch(Facebook\Exceptions\FacebookSDKException $e) {  // When validation fails or other local issues  echo __LINE__ . ' Access Token: Facebook SDK returned an error: ' . $e->getMessage();  exit;}if (! isset($accessToken)) {  if ($helper->getError()) {    header('HTTP/1.0 401 Unauthorized');    echo "Error: " . $helper->getError() . "\n";    echo "Error Code: " . $helper->getErrorCode() . "\n";    echo "Error Reason: " . $helper->getErrorReason() . "\n";    echo "Error Description: " . $helper->getErrorDescription() . "\n";  } else {    header('HTTP/1.0 400 Bad Request');    echo __LINE__ . ' Access Token: Bad request';  }  exit;}$get = "?accessToken=" . $accessToken;?><html><head>  <script type='text/javascript' src='jquery.js'></script>  <script>    var $j = jQuery.noConflict();    $j(document).ready(function () {      $j.ajax({        type: "GET",        url: "get-posts.php<?php echo $get; ?>",        cache: false,        success: function (html) {          setTimeout(function () {            $j('#updateDiv').html(html);          }, 1000);        }      });    });  </script>    </head>    <body>        <div id='updateDiv'><img src='spinning.gif' alt='processing...'></div>     </body></html>

get-posts.php

<?phprequire_once("config.php");$fb->setDefaultAccessToken($_GET['accessToken']);...

So what changed? First, I needed to get the access code in fb-callback.php, not get-posts.php. So I moved the logic to get the access code and check for errors back to fb-callback.php. Then I added some logic to pass the access token collected to the parameter string of the AJAX url. (Look for "$get" in two places, once where I set the value and once where I attach it to the AJAX url.)

In get-posts.php, I removed the code that asks the Facebook API for an access token. Instead, I merely set the access token based on what was passed from fb-config.php via GET in the parameter named "accessToken" with the setDefaultAccesstoken() function from the Facebook PHP SDK.

As noted elsewhere, you can keep passing along the value of the access token via GET, REQUEST, or $_SESSION to page after page, so long as you maintain a session and inform Facebook via the setDefaultAccessToken() function at each subsequent page.


The answer is in the comments, but there are actually better ways.


Firstly, to answer your question directly, the issue is that the "code" passed to the fb-callback.php has not been passed to the script that calls $helper->getAccessToken()

The docs for that function (at https://developers.facebook.com/docs/php/FacebookRedirectLoginHelper/5.0.0) states

Attempts to obtain an access token from an authorization code. This method will make a request to the Graph API and return a response. If there was an error in that process a FacebookSDKException will be thrown. A FacebookSDKException will also be thrown if the CSRF validation fails.

If no authorization code could be found from the code param in the URL, this method will return null.

There are two other points to note:

  • The "state" (cross site forgery token) is part of the session; you do notneed to explicitly pass it in so long as you're on the same domain,however you may need session_start() in both login andget-posts scripts There is a parameter to the getAccessTokenfunction which should be the URL of the ORIGINAL

So very simply

  1. Add session_start() to the login script and the get-posts.php
  2. Modify the fb-callback.php to be something like

.

<?phprequire_once("config.php");$code = $_GET['code'];   // warning: add validation code exists, sanitise etc.?><html><head>  <script type='text/javascript' src='jquery.js'></script>  <script>    var $j = jQuery.noConflict();    $j(document).ready(function () {      $j.ajax({        type: "GET",        url: "get-posts.php?code=<?php echo $code; ?>",        cache: false,        success: function (html) {          setTimeout(function () {            $j('#updateDiv').html(html);          }, 1000);        }      });    });  </script>    </head>    <body>        <div id='updateDiv'><img src='spinning.gif' alt='processing...'></div>     </body></html>

(Note: I hate inline PHP - this is example only)


However: what you should be doing is passing the Access Token between functions and not the oAuth code. The way you have it above (passing the oAuth code) is a one-off; however you can call get-posts a second/third/fourth time and it'll work if you have the access token first.

1) Do the token exchange in fb-callback.php at the top (it's fast, no need for spinner), grab the token (which FB library stores in a session variable/cookie, or you can do it yourself) and then show the HTML page with spinner and AJAX call.

2) Do the token exchange in fb-callback.php at the top (it's fast, no need for spinner), grab the token (which FB library stores in a session variable/cookie, or you can do it yourself) and then quickly redirect to another page that shows the spinner and does AJAX call.

The critical think to note in both of these is you are passing the Access Token; in get-posts.php check "do I have access token; if not - show login button; if so - call facebook".