As the Facebook PHP SDK v4.0 gets closer and closer to the next big release of version 4.1 (probably in August or September of 2014), the internal structure keeps getting more and more decoupled. And that's a very, very good thing!
But good things have also recently happened in the 4.0 branch. In version 4.0.9 access token handling has been completely decoupled, and it is now possible to work directly with access tokens with the SDK.
Note: This syntax of the examples used throughout this post are for version 4.0 of the SDK. The syntax will be changing soon in version 4.1.
What is an access token?
An access token is basically a really long ID that is required in order to make calls to the Graph API. The token identifies the following:
- The Facebook app ID that is making the request
- The Facebook user ID that the request is associated with (if applicable)
- The page ID that the request is associated with (if applicable)
It also contains information about the time in seconds until the access token expires and sometimes contains an identifier called a machine_id
that identifies the computer that requested the access token. The machine_id
is used to verify the access token's authenticity.
Short-lived vs long-lived access tokens
By default, when you request a user access token, Facebook will return a short-lived access token which will expire in 2 hours. Or as the official documentation states, "about an hour or two". I'm not sure the reason for the fuzzy time explanation.
This short amount of time could be problematic if you plan on storing the access token in your database and using it to make requests to Graph later. So you'll need to exchange the short-lived access token for a long-lived access token which will be valid for 2 months before it expires.
In order to extend your short-lived access token with a long-lived access token, you'll need to use the new AccessToken
entity from the SDK (see below).
Types of access tokens
There are a number of different access tokens that can be used to interact with Graph. For convenience, Facebook provides an access token tool that lists access tokens for the various apps that you administrate. There's also an access token debugger that will decode an access token and return the underlying identifying data.
But not all access tokens are the same. Depending on what you want to do, you'll need to send a different token with your request to Graph.
User access token
Perhaps the most well-know and widely used access token is the user access token. This is the access token you want to use when making calls to Graph on behalf of a specific user.
A user access token looks like this:
CAABwiWr8tH8BAGKCYOIgoMwJ9T0ZAmJ6KJJNcUjzmftdAOCx1RgzxZAjzGB1s37DDCEoy9r2VgrCLffCTvEGe9cZBZPAwBhygi2ZpTubZC2eCzMe16CLP4Wlc9bStWGwUNYoLEl4dXu4uJl2CCLiFXEtP4GKDv0Gk4s35iXty77KZBx5NYBCcEUs98WjdJQcXLsb1X2ZBaMTW2AZDZN
And a user access token will allow you to:
- Get information on the user.
- Post/update/delete on behalf of the user assuming the user has granted the proper permissions.
- Long-lived tokens can be used to generate new long-lived access tokens using a code.
Obtaining a user access token
User access tokens can be obtained via the Facebook PHP SDK v4 "helpers". The most common helper is the FacebookRedirectLoginHelper
which will obtain an access token via a redirect link.
session_start();
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookSDKException;
$helper = new FacebookRedirectLoginHelper('{callback-url}', '{app-id}', '{app-secret}');
try {
$session = $helper->getSessionFromRedirect();
} catch(FacebookSDKException $e) {
$session = null;
}
if ($session) {
// User logged in, get the AccessToken entity.
$accessToken = $session->getAccessToken();
// Exchange the short-lived token for a long-lived token.
$longLivedAccessToken = $accessToken->extend();
// Now store the long-lived token in the database
// . . . $db->store($longLivedAccessToken);
// Make calls to Graph with the long-lived token.
// . . .
} else {
echo '<a href="' . $helper->getLoginUrl() . '">Login with Facebook</a>';
}
Note: The base hostname of the callback URL needs to be defined in the app settings. You'll need to browse to your app in the list of your Facebook apps. Then navigate to the "Settings" tab. In the "App Domains" field, enter any host names you'll be using. Then click, "Add Platform" and choose, "Website". Enter the root URL of your redirect URL in the "Site URL" field.
Page access token
A page access token looks just like a user access token. It also identifies the target page ID. This is the token you want to use to perform actions on behalf of a specific page such as:
- Manage the information on the page profile.
- Post/update/delete on behalf of the page.
Obtaining a page access token
Page access tokens can be obtained from a user who has administrator privileges to the target page and has also authorized your app with the manage_pages
permission.
use Facebook\FacebookRequest;
// Assuming $session was obtained from a helper...
// Get a list of pages that this user admins; requires "manage_pages" permission
$request = new FacebookRequest($session, 'GET', '/me/accounts?fields=name,access_token,perms');
$pageList = $request->execute()
->getGraphObject()
->asArray();
foreach ($pageList as $page) {
$pageAccessToken = $page['access_token'];
// Store $pageAccessToken and/or
// send requests to Graph on behalf of the page
}
The page access tokens that are returned from the /me/accounts
endpoint will expire by default if you used a short-lived user access token to obtain them. If you used a long-lived user access token to obtain them, the /me/accounts
endpoint will return page access tokens that never expire.
You'll also notice a perms
array is returned that lists the administrative permissions that the user has on this page.
App access token
An app access token looks like this:
1234567890|EnEYhJBbcc-gm84CeUivNgC0bZZ
The token is made up of the app ID and the app secret or a valid hash of the app secret. An app access token will allow you to manage the app information including:
- Test users
- Banned users
- Real-time update subscriptions
- User roles
- And more...
Obtaining an app access token
App access tokens don't require any calls to Facebook to obtain. You can make an access token by concatenating the app ID with the app secret and using a pipe delimiter.
{app-id}|{app-secret}
App access tokens don't expire. And since they contain the app secret, you never want to use them on the client side.
The new AccessToken
entity
You saw it first in the Facebook Query Builder and now the AccessToken
entity has been ported into the official SDK.
Extending a short-lived access token
Once you obtain a valid FacebookSession
with the redirect, canvas or javascript helper, you can use getAccessToken()
to get the AccessToken
entity. Since the first access token you receive will be short-lived, you can easily extend()
it to make a long-lived access token.
use Facebook\FacebookSDKException;
// Assuming $session was obtained from a helper...
// Get the AccessToken entity.
$accessToken = $session->getAccessToken();
try {
// Exchange the short-lived token for a long-lived token.
$longLivedAccessToken = $accessToken->extend();
} catch(FacebookSDKException $e) {
echo 'Error extending short-lived access token: ' . $e->getMessage();
exit;
}
// Now store the long lived token in the database
// . . . $db->store($longLivedAccessToken);
// Make calls to Graph with the long lived token.
// . . .
Getting detailed information about an access token
The Graph API has a useful /debug_token
endpoint that you can use to get information about an access token. And the SDK supports this functionality right out of the box.
use Facebook\Entities\AccessToken;
use Facebook\FacebookSDKException;
$accessToken = new AccessToken('{my-access-token}');
try {
// Get info about the token
// Returns a GraphSessionInfo object
$accessTokenInfo = $accessToken->getInfo();
} catch(FacebookSDKException $e) {
echo 'Error getting access token info: ' . $e->getMessage();
exit;
}
// Dump the info about the token
var_dump($accessTokenInfo->asArray());
Of course if you just want to debug a token while you're developing your app, you can always use the convenient debugger provided by Facebook.
Best practices for maintaining long loved access tokens over time
If your app is sending requests with a long-lived access token to the Graph API on behalf of your users frequently, your app is at risk of being flagged for spam. In order to avoid this, you can use a code to get new long-lived tokens.
The basic flow goes something like this:
- Retrieve the long-lived user access token from your database.
- Use the long-lived token to request a code.
- Use the code to request a new long-lived access token.
- Use the new long-lived access token to make calls to Graph on the user's behalf.
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\Entities\AccessToken;
use Facebook\FacebookSDKException;
$longLivedAccessToken = new AccessToken('{long-lived-access-token}');
try {
// Get a code from a long-lived access token
$code = AccessToken::getCodeFromAccessToken($longLivedAccessToken);
} catch(FacebookSDKException $e) {
echo 'Error getting code: ' . $e->getMessage();
exit;
}
try {
// Get a new long-lived access token from the code
$newLongLivedAccessToken = AccessToken::getAccessTokenFromCode($code);
} catch(FacebookSDKException $e) {
echo 'Error getting a new long-lived access token: ' . $e->getMessage();
exit;
}
// Make calls to Graph using $shortLivedAccessToken
$session = new FacebookSession($newLongLivedAccessToken);
$request = new FacebookRequest($session, 'GET', '/me');
$userData = $request->execute()
->getGraphObject()
->asArray();
var_dump($userData);
<<EOF;
As you can see access tokens aren't as confusing as they seem at first. Since the SDK makes it so easy to handle access tokens, the hardest part on your end is figuring out which access token you'll need to solve your particular problem.
If you want to dive deeper, check out the official access token documentation on Facebook.