Facebook offline access step-by-step

With the new Facebook Graph API, things got a bit simpler but far less well documented. Here's what I did to be able to load my wall posts as me from a server side only (not part of a browser session) php script:

  1. create a facebook application, if you don't already have one usable for this project http://www.facebook.com/developers/apps.php#!/developers/createapp.php -- and set sandbox/developer mode on! @ Advanced Settings > Sandbox Mode > Enable (Lets only the developers of your application see it.) You'll need the Application ID (APP_ID) and Secret Key (SECRET_KEY) that are listed on your developer account summary of that application but not the old API Key.

  2. load in your browser, already logged in to fb as the account you want your server side app to connect as, and click "allow" for the requested permissions: https://graph.facebook.com/oauth/authorize?client_id=APP_ID&scope=offline_access,read_stream&redirect_uri=http://www.facebook.com/connect/login_success.html

  3. copy the "code" parameter from the resulting url's query string, use that in: https://graph.facebook.com/oauth/access_token?client_id=APP_ID&redirect_uri=http://www.facebook.com/connect/login_success.html&client_secret=APP_SECRET&code=CODE_FROM_2 And copy the right hand side of access_token= in the resulting page's text, which will be in the structure of: APP_ID|HEXNUM-USER_ID|WEIRD_KEY

  4. now download either from the graph api or the classic rest api using the oath access token you just got ala (where SOURCE_ID is the facebook id for the user/group/whatever that you are looking up):

    <?php
    $stream = json_decode(file_get_contents("https://api.facebook.com/method/stream.get?source_ids=SOURCE_ID&access_token=ACCESS_TOKEN&format=json"));
    var_dump($stream);
    // this one gives a 500 internal server error from the http get if any of the fields are invalid, but only in php, not when loaded in a browser... weird.
    $feed = json_decode(file_get_contents("https://graph.facebook.com/SOURCE_ID/feed?fields=id,from,created_time,link,type&access_token=ACCESS_TOKEN"));
    var_dump($feed);
    ?>
    

Noting that the graph api and rest api return not just different structures, but also different information -- so here, I prefer the results from the rest api (the first one) even though I like being able to restrict the fields in the new graph api (the second one).

Look at http://developers.facebook.com/docs/authentication/ in the sections "Requesting Extended Permissions" and "Authenticating Users in a Web Application" for the official (sparse) details.

If you want to do this routinely, i.e. programmatically, here's the automated version of steps 2+3:

Put this on your web server as "facebook_access_token.php":

<?php $token = explode('=', file_get_contents("https://graph.facebook.com/oauth/access_token?client_id=APP_ID&redirect_uri=http://$_SERVER[SERVER_NAME]$_SERVER[PHP_SELF]&client_secret=APP_SECRET&code=" . 
(get_magic_quotes_gpc() ? stripslashes($_GET['code']) : $_GET['code']))); 
echo $token[1]; 
// store this, the access token, in the db for the user as logged in on your site -- and don't abuse their trust! ?>

And direct users in their browsers to: https://graph.facebook.com/oauth/authorize?client_id=APP_ID&scope=offline_access,read_stream&redirect_uri=http://www.example.com/facebook_access_token.php


If you want finally want to use PHP, with the Facebook PHP SDK v3 (see on github), it is pretty simple. To log someone with the offline_access permission, you ask it when your generate the login URL. Here is how you do that.

Get the offline access token

First you check if the user is logged in or not :

require "facebook.php";
$facebook = new Facebook(array(
    'appId'  => YOUR_APP_ID,
    'secret' => YOUR_APP_SECRET,
));

$user = $facebook->getUser();

if ($user) {
  try {
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) {
    $user = null;
  }
}

If he is not, you generate the "Login with Facebook" URL asking for the offline_access permission :

if (!$user) {
    $args['scope'] = 'offline_access';
    $loginUrl = $facebook->getLoginUrl($args);
}

And then display the link in your template :

<?php if (!$user): ?>
    <a href="<?php echo $loginUrl ?>">Login with Facebook</a>
<?php endif ?>

Then you can retrieve the offline access token and store it. To get it, call :

if ($user) {
    $token = $facebook->getAccessToken();
    // store token
}

Use the offline access token

To use the offline access token when the user is not logged in :

require "facebook.php";
$facebook = new Facebook(array(
    'appId'  => YOUR_APP_ID,
    'secret' => YOUR_APP_SECRET,
));

$facebook->setAccessToken("...");

And now you can make API calls for this user :

$user_profile = $facebook->api('/me');

Hope that helps !