By Rok Dominko

2012-01-24 04:30:03 8 Comments

Since the offline_access Permission is deprecated in Facebook's Authentication flow, we have problem geting the so called long lived access tokens without that permission.

In Facebook's document about the deprecation it says, that server side OAuth generated access tokens will be long lived, but they are not.

Am I missing something? Some setting in app settings? Some special code I need to use to extend expiration time of access tokens? As I understand the documentation, for server side authentication, the access token wich can be accessed by getAccessToken() method of PHP SDK when the user is logged in is long lived.


@Sung Kim 2016-02-08 04:27:16

Inspired by previous answers, I wrote a simple token self-renewal program. First, just put your current token in the 'token.sec' file.

This program will read a token from the file, and update with a new token if everything is OK. In other programs, you just need to use the token:

$access_token = file_get_contents("token.sec");

Here we are:

$app_id = "<your app id>";
$app_secret = "<your app secret>";
$access_token = file_get_contents("token.sec");

   . "grant_type=fb_exchange_token"
   . "&client_id=" . $app_id 
   . "&client_secret=" . $app_secret
   . "&fb_exchange_token=" . $access_token;

$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch); 
if($response === false) {
    die ('Curl error: ' . curl_error($ch));

// Close handle

// parse the output
parse_str($response, $params);
if(!isset($params['access_token'])) {
    die("No access token");

echo ("New token: $access_token\n");

// eveything looks OK
rename("token.sec", "token.sec.back"); // just in case
$myfile = fopen("token.sec", "w") or die("Unable to open file!");
fwrite($myfile, $access_token);

Finally, we can add this in our crontab to renew the token once per momth:

0 0 1 * * cd /home/<path>; php exchangeToken.php

@Aaron Dartt 2013-04-01 11:15:43

this is for extending pages access token to expiring never, and extending the life of user access tokens expiring after 2 months(the 'new access token').

Ok so it took about a week of research but here is my solution. in the make sure that you have manage_page as part of your access_token. after that use this code with your app id, secret, and redirect:

   app_id = "APP_ID";
   $app_secret = "APP_SECERET";
   $post_login_url = "REDIRECT_URL";

   $code = $_REQUEST['code'];

   //Obtain the access_token with publish_stream permission 
      $dialog_url= ""
       . "client_id=" .  $app_id 
       . "&redirect_uri=" . urlencode( $post_login_url)
      echo("<script>top.location.href='" . $dialog_url 
      . "'</script>");
    else {

       . "client_id=" . $app_id 
       . "&redirect_uri=". urlencode($post_login_url)
       . "&client_secret=" . $app_secret
       . "&code=" . $code;
      $response = file_get_contents($token_url);
      $params = null;
      parse_str($response, $params);
      $access_token = $params['access_token'];
      echo 'access token: ' . $access_token.'<br>';


       . "client_id=" . $app_id 
       . "&redirect_uri=". urlencode($post_login_url)
       . "&client_secret=" . $app_secret
       . "&fb_exchange_token=" . $access_token;
       $response = file_get_contents($token_url);
       $access_token = $params['access_token'];
       echo 'new access token: '.$access_token;



After that copy the 'new access token' and go back to When you get there past in your new access token into the the access token field. Then click submit. After that in the node you will see a +____ click on this and scroll down to the accounts and click that. find the page that you need the access token for and copy and paste it into the access key field. click debug and you will see that it will never expire. save that token it will stay valid as long as you do not reset your apps secret.

@Pete 2012-12-18 07:21:13

Should you need an access token that NEVER expires for a PAGE, see my answer to a similar question here

From the developers page:

By using a long-lived user access token, querying the [User ID]/accounts endpoint will now provide page access tokens that do not expire for pages that a user manages.

@Juicy Scripter 2012-01-24 07:17:54

Actually what was said:

If the access_token is generated from a server-side OAuth call, the resulting access_token will have the longer expiration time. If the call is made while there is still a valid access_token for that user, the returned access_token from this second call will remain the same and only the expiration time will be extended. Again, calling this multiple times during the same day will result only in the first call extending the expiration time.

Which means that it will be just longer than client-side generated token, and to receive extended token (60 days) you need do it manually by issuing request to:             

This token can still became invalid for several reasons, and how to handle this described in How-To: Handle expired access tokens blog post.

As of Aug 07, 2012 you can use setExtendedAccessToken method to extend access_token instead of manually constructing URL and retrieving details.

@Nikolay Kuznetsov 2012-10-26 08:06:23

Vote up! Does always give the same access_token with extended expiration time? Or access_token might be changed?

@Joseph 2012-10-26 18:52:34

Pretty sure you'll always get the same token, since you're extending a pre-existing token. Facebook says the times you may get a new token is when the user changes their password and/or logs out and logs back into your app.

@Marc Hoogvliet 2012-01-27 14:45:17

Edit (August 14th 2012):
A week ago the official Facebook PHP SDK was updated. The function name was changed to setExtendedAccessToken, and it was decided we actually needed to destroy the session afterwards, to remove the risk of having two active sessions.
Also, the function no longer actually returns the token, but instead stores it within the persistant data. You can therefore get the new access token with the public function getAccessToken afterwards. Grab the new SDK from official Facebook PHP SDK github page to make sure you're up to date.

Original Answer:

I have added a new public function to the base_facebook.php file, which returns an new access token which expires in 60 days. You can make a request to this function after you've received the normal access token. I've not tested, but I assume you also need to enable 'deprecate offline_access" in your Advanced settings of the Developer App.

Just add this to your base_facebook.php inside the facebook class and make a call to it. It works for me.

 public function getExtendedAccessToken(){

    try {
        // need to circumvent json_decode by calling _oauthRequest
          // directly, since response isn't JSON format.
        $access_token_response =
                $this->getUrl('graph', '/oauth/access_token'), array(
                    'client_id' => $this->getAppId(),
                    'client_secret' => $this->getAppSecret(),
    } catch (FacebookApiException $e) {
      // most likely that user very recently revoked authorization.
      // In any event, we don't have an access token, so say so.
      return false;

    if (empty($access_token_response)) {
      return false;

    $response_params = array();
    parse_str($access_token_response, $response_params);
    if (!isset($response_params['access_token'])) {
      return false;

    return $response_params['access_token'];

@Thomas Kekeisen 2012-02-09 15:08:08

In my case I had to replace "getAppSecret()" with "getApiSecret()" (SDK version 3.1.1)

@Marc Hoogvliet 2012-02-11 13:29:02

Doesn't the getApiSecret function just returns the getAppSecret function in SDK 3.1.1 as the getApiSecret function is depreciated and will be removed in future versions?

@DaveB 2012-04-23 09:22:51

Can someone tell me if this will work with access tokens obtained using the signed_request approach? Because the facebook docs seem to say it is only for the client-side flow?

@Yura Shinkarev 2012-06-20 14:22:40

Boyes, does it worked now? I try, but get error as this:…

@Chris Jacob 2012-07-17 14:26:51

And to check your access_token var_dump() it then copy and paste the string into: ... you want to see something like "Expires: 1347718933 (in about 2 months)". If you see something like "Expires: 1342540800 (in about an hour)" then you haven't got the extended access token. Compare the results of getAccessToken() vs this answers getExtendedAccessToken(). Good luck!.

@Chris Jacob 2012-07-17 14:41:07

I've added a Facebook Bug Report to suggest this function be included in the official SDK. Find it here:

@user1058210 2012-08-15 15:02:05

My access token is automatically being stored in a session variable which I echoed out. I then called setExtendedAccessToken() and echoed it out again. The access token had changed, but after checking it using the access token debugger it still had a lifetime of 2 hours. I tried running the setExtendedAccessToken() method again but the access token did not change. It is mentioned in the docs that you can only call it once per day, so it looks like it could have worked. Why has it not changed the lifetime though?

@Julian H. Lam 2012-09-28 14:49:10

I've detailed some findings and added a possible workaround in this related question:…

@gokul bs 2012-03-05 07:11:54

//using a javascript for popup for facebook login

FB.login(function(response) {

            if (response.authResponse) {

                   var accessToken = response.authResponse.accessToken;

//got the accesstoken with 1-2 hours expire time

//got the accesstoken into a controller called facebook controller

        $request = $this->getRequest();
        $params = $request->getParams();

//taking the access token to extend to 60days

        $conf = $this->getConfigs();
        $appid = $conf['fbdetails']['appid'];
        $secret = $conf['fbdetails']['secret'];
        $baseurl = $conf['app']['baseurl'];

//After the execution of below code , we will have a response with acess token expire time to 60days.

        $token_url = "".$appid."&client_secret=".$secret."&grant_type=fb_exchange_token&fb_exchange_token=".$token;

// Above response is given for parsing.

        $c = curl_init();
        curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($c, CURLOPT_URL, $token_url);
        $contents = curl_exec($c);
        $err  = curl_getinfo($c,CURLINFO_HTTP_CODE);

        $paramsfb = null;
        parse_str($contents, $paramsfb);

//after the parsing the contents in the above execution code the new extended accesstoken is stored.

        $user_session = new Zend_Session_Namespace('fbuser');
        $user_session->access_token = $paramsfb['access_token'];

//stored to session.


//Have a nice coding

@Robert Kajic 2012-04-04 16:17:30

An access token generated through a server-side OAuth call will be of the extended (longer) kind and you don't need to exchange it. It is already an extended token. The only thing you must do is enable "Deprecate offline access" in your app settings. This is of course only necessary if "Deprecate offline access" was previously disabled.

Then, when you authenticate users through Facebook you will receive an access token that lives for 60 days. Authenticating multiple times during the same day will result only in the first authentication extending the expiration time.

@Tom 2012-04-06 22:40:12

I also experience this behavior. In fact, calling the endpoint in the documentation asked me for a redirect_uri again and when I provided a matching one (from previous calls), it came back with an error. I have not been able to successfully call the method to get an extended token. HOWEVER, my tokens DO last for 60 days since I made the OAuth call server-side and have the deprecate offline access option checked as enabled. So I can make another normal request to get another 60 days (I guess once per day). I really wish this could be automated...Bugging the user to re-auth every 60 is horrible.

@Robert Kajic 2012-04-10 12:30:11

Actually the re-authentication should be completely transparent for your users. Keep in mind they've authenticated your application already, even if your access token has expired. Regarding the extend expiration endpoint (, which you tried to use without success - it didn't work because it's only supposed to be used for Client-side OAuth.

Related Questions

Sponsored Content

2 Answered Questions

12 Answered Questions

[SOLVED] What is the purpose of the implicit grant authorization type in OAuth 2?

4 Answered Questions

1 Answered Questions

[SOLVED] Extending Long-lived access tokens

2 Answered Questions

1 Answered Questions

2 Answered Questions

[SOLVED] How long do 'offline_access' OAuth tokens last for?

Sponsored Content