8
votes

I try to get extended long-lived access token with

$facebook->setExtendedAccessToken();
$access_token = $facebook->getAccessToken();

After looking SDK I found that setExtendedAccessToken() function is setting long-lived access token in

protected static $kSupportedKeys =
array('state', 'code', 'access_token', 'user_id');

with

$this->setPersistentData(
  'access_token', $response_params['access_token']
);

and getAccessToken() is returning short-lived access token from

protected $accessToken

so what is the purpose of setExtendedAccessToken() since it does not return anything?

2
I also hope that someone could give any helpful answer to that question.Frank Myat Thu

2 Answers

12
votes

@Julian. Thank you so much for the inspiration here. I was able to make this work without changing any of the core FB api files.

What happens is, the setExtendedAccessToken call sends the value to setPersistentData which then sends it into session via constructSessionVariableName.

So if we get it out of session, and then set it into the facebook object, we're all set.

Here is my code:

// ask for the extended token and get it from session ...
$facebook->setExtendedAccessToken();
$access_token = $_SESSION["fb_".FB_APP_ID."_access_token"];
// now set it into the facebook object ....
$facebook->setAccessToken($access_token);
// now our fb object will use the new token as usual ...
$accessToken = $facebook->getAccessToken();
5
votes

After further attempt to poke around base_facebook.php, I have discovered the following:

  • setExtendedAccessToken(); will exchange a short-lived access token and Facebook will return a proper extended access token.
  • setExtendedAccessToken(); saves this in the persistent data cache, but this doesn't mean getAccessToken(); can access it, because getAccessToken(); doesn't query the persistent cache. Furthermore, the class seems to treat the persistent data as a "failsafe", and only uses it if all other attempts to retrieve data have failed (that is, after checking signed_request, and parsing a code).
  • In our case, the access token returned via setExtendedAccessToken(); is the most recent access token, so I hacked in a fix. Add the following line at the bottom of setExtendedAccessToken();

    // Also set the publically accessible access token value to this new extended token

    $this->accessToken = $response_params['access_token'];

  • Caveat: Even though we now have the new extended access token, subsequent queries to Facebook to retrieve an access token (e.g. after a page refresh) will return the same old short-lived access token. *facepalm*

  • Even after the user logs out (thus causing the short-lived token to expire), and logs back in, Facebook will again return a short-lived access token.
  • However, even though this is the case, setExtendedAccessToken(); will return the same extended access token you retrieved earlier. This token is still usable to query user information.

So, this looks like a Facebook bug, as much as I hate saying it. We can get around it with the hack I have detailed above, and any subsequent calls to fetch an access token will just return a short-lived access token, which can be exchanged again and again for the same extended access token.


Original Answer

According to this answer, the new access token is saved in the persistent data (as you have also indicated in your question), and can be accessed via $facebook->getAccessToken();.

Two relevant notes:

  • This page also mentions that when the short-lived access token is exchanged for an extended access token, the token itself may or may not change, although the expiry time should have updated to reflect the longer expiration. Perhaps when you call $facebook->getAccessToken();, you are merely getting the same token back, but its expiration has changed?
  • The call to exchange a short-lived access token for an extended one can only be made once a day per user. I don't know why this is, and I don't know whether this counter is reset if a user decides to de-authorize your app and re-authorize.

From the Facebook documentation:

When a user visits your site with an existing, valid, short-lived user access_token, you have the option to extend the expiration time of that access token. Our platform will only extend the expiration time once per day, so even if a user revists your site multiple times a day, the token will be extended the first time requested. (emphasis mine)

I believe this is the case because sloppy programmers will call $facebook->setExtendedAccessToken(); at every possible opportunity, in the hopes of always retrieving an extended access token. (Instead of the preferred behaviour, which would be only calling $facebook->setExtendedAccessToken(); if what you currently have is a short-lived access token -- but how would you even tell unless you've saved the expiration date, which in and of itself isn't that reliable...!)

My assumption is that if a user de-authorizes the app, or the token otherwise invalidates, the limit will reset, and you will be able to once again retrieve an extended access token when passing in a short-lived access token. However, this requires further testing, so please take this paragraph with a grain of salt.