12

Facebook has removed the offline_access token functionality, now tokens have to be renewed whenever the user visits your website to keep them active.

Say someone has already given your website access and you have a token stored for them. What code would you use with Facebook's PHP library to renew that token?

Ali
  • 261,656
  • 265
  • 575
  • 769
  • 1
    What do you use tokens for? If you have enough permissions - you don't need to retrieve and store user session tokens, and just use application ones – zerkms Apr 05 '12 at 02:31
  • @zerkms If a user clicks to share a story on his profile on my website, then I'd like to use Ajax to post the story on his FB profile without having to redirect him to facebook each time. – Ali Apr 05 '12 at 02:33
  • then you just need to retrieve `publish_stream` permission (http://developers.facebook.com/docs/authentication/permissions/#extended_perms, see description ). As long as you have it - you can just post the updates, without user's tokens – zerkms Apr 05 '12 at 02:36
  • @zerkms Then what's the point of access tokens, what are they used for now? – Ali Apr 05 '12 at 02:37
  • for example - to authenticate user, and in some cases - to authorize actions (not all actions have correspondent extended permissions) – zerkms Apr 05 '12 at 02:38
  • @zerkms Ok. I'd appreciate if you could still answer the question with the code for renewing the tokens, just so if something I'm trying to do requires authentication, then I'd be able to use the tokens. – Ali Apr 05 '12 at 02:39
  • you cannot refresh them rather than forward user to a facebook. And this is what you know how to do and want to avoid. – zerkms Apr 05 '12 at 02:41
  • ps: "Say someone has already given your website access and you have a token stored for them." --- this is incorrect for facebook. You shouldn't persist user tokens for facebook ever – zerkms Apr 05 '12 at 02:42
  • @zerkms Do you remember the offline_access token setting? I'm basically trying to replace that. – Ali Apr 05 '12 at 02:45
  • Yep, and you just need to retrieve `publish_stream` permission and remove user tokens. And it should work ;-) – zerkms Apr 05 '12 at 02:58
  • 1
    @zerkms, I get lost in facebook api documentation, so maybe you can quickly answer this. Are you saying that as long as a user authorizes my App for a set of permissions, I don't need to provide any access tokens in my PHP API (get or post) calls to Facebook (within allowed permissions set) if I specify APP ID and APP SECRET? thanks. – Alexey Gerasimov Apr 08 '12 at 03:59
  • @Alexey Gerasimov: exactly. As long as **your application** has the permission - you don't need anything else, just application tokens – zerkms Apr 08 '12 at 04:02
  • @zerkms, thanks. Still confused though. I assume, by app token you mean ones in http://developers.facebook.com/docs/authentication/#applogin. If that's the case, that's what I also meant by needing the token. The token that you get back when the user authorizes your app. I also believe, that's what Click Upvote meant. Maybe not. What if I wanted to (at night) determine which permissions users gave me programatically. You're saying that I don't need provide the access_token as FB doc says: https://graph.facebook.com/me/permissions?access_token=USER_ACCESS_TOKEN. That's one reason I'd store it. – Alexey Gerasimov Apr 08 '12 at 04:32
  • @Alexey Gerasimov: "You're saying that I don't need provide the access_token" --- I'm not saying that, I'm saying that we don't need personal user token that belongs to a particular user session (that said "permanent" ones). – zerkms Apr 08 '12 at 06:10
  • @Alexey Gerasimov, If we no need access_token, then I think our application user will need to login every time when he/she want to post data to our created facebook page. If so , our app will need user interaction in every time. I don't want that style. – Frank Myat Thu Sep 16 '12 at 23:46
  • So , I prefer access_token which no need user interaction as long as its expiration date not come. – Frank Myat Thu Sep 16 '12 at 23:49
  • A user token is now always required to publish to a user's Facebook timeline. The "publish_stream" API method that didn't require a user token, no longer exists. – Doug S Sep 29 '15 at 02:35

4 Answers4

8

You can extend your token the following way:

Original scenario

  • Your app requests permissions from the user
  • You prompt user to log in / grant permissions
  • You get user's token (short-lived one) and exchange via CURL or other means for a 60 day one using grant_type=fb_exchange_token
  • You persist the token

Now you have that token to do what you wish with it for up to 60 days. Up to, because user can change password, de-authorize app, etc and token would become invalid. What you can do to extend the token is EVERY TIME user comes to your page(s), you can check if they are logged in via javascript and if they are, make an ajax call to your server to extend existing token for 60 days from today. You can make as many calls as you want, only the first one is valid. Here's how I do it:

  1. On your page somewhere during load event, add something like:

     FB.getLoginStatus(function (response) {
         if (response.status === 'connected') {
            $.ajax({
                type: "POST",
                async: false,
                url: YOUR_URL,
                dataType: "text",
                data: {token  : response.authResponse.accessToken }
             });
         }
     });
             //rest of jquery ajax call here
    

That will get a new client-side access token for the user and send it to the server

  1. Server can then take that token and exchange it for a 60 day one

    $token_url = "https://graph.facebook.com/oauth/access_token?client_id=".FACEBOOK_CLIENT_ID."&client_secret=".FACEBOOK_SECRET."&grant_type=fb_exchange_token&fb_exchange_token=".$token;
    
    $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);
    curl_close($c);
    
    $paramsfb = null;
    parse_str($contents, $paramsfb);        
    

Reference:

https://developers.facebook.com/roadmap/offline-access-removal/

That would only extend the token if the user comes back to your site within 60 days. If not, you will need to prompt for permissions again.

Khalid Dabjan
  • 2,697
  • 2
  • 24
  • 35
Alexey Gerasimov
  • 2,131
  • 13
  • 17
  • Thanks for the answer. Rather than using CURL, isn't there a way to do this using Facebook's own class that they provide? – Ali Apr 09 '12 at 02:19
  • @Click Upvote, probably but I tried to use the FB class and doing api->('/oauth/access_token, 'get', $data) and various permutations but for some reason wasn't getting any data back. Didn't have time to figure out so cheated by doing curl. FB class does CURL too so I am sure it was just some syntax errors on my part. If you figure it out, let me know :) I'd appreciate it – Alexey Gerasimov Apr 09 '12 at 14:13
  • 1
    Facebook PHP SDK (v.3.2.2) has a method to achieve this: Base_Facebook::setExtendedAccessToken() – Lucia Aug 15 '13 at 18:55
1

Updated

Yes @zerkms is right, no access_token is needed if the application has permission.

With this permission, you can publish content to a user's feed at any time. However, please note that Facebook recommends a user-initiated sharing model. Please read the Platform Policies to ensure you understand how to properly use this permission. Note, you do not need to request the publish_stream permission in order to use the Feed Dialog, the Requests Dialog or the Send Dialog.

All extended permissions have similar privileges: https://developers.facebook.com/docs/authentication/permissions/

Adam
  • 16,089
  • 6
  • 66
  • 109
  • "You will need to get the user to reauthenticate again within 60 days to grab a new token." --- nope. As long as there is `publish_stream` permitted - you don't need user's tokens ever. Until user deletes the application from apps list - you can post the messages, even after 100 years. So, no, there is no reason to persist any token additionally to application key and secret – zerkms Apr 05 '12 at 09:02
  • just answer my question, how do i renew tokens, this isnt about stream publishing – Ali Apr 05 '12 at 13:50
  • you renew tokens by getting people to go through the authentication process again. You can't automatically renew tokens, otherwise what is the point of having an expiration date on them. – Adam Apr 05 '12 at 14:19
0

Here's what im currently doing

public function setExtendAccessToken($accessToken = NULL) {

enter code here
    if(!$accessToken) return;

    $graphUrl = 'https://graph.facebook.com/oauth/access_token?client_id='.$facebookAppId.
                '&client_secret='.$facebookSecret.
                '&grant_type=fb_exchange_token&fb_exchange_token='.$accessToken;
    $accessToken = @file_get_contents($graphUrl);
    parse_str($accessToken); //get the access_token param in the string and would be named $access_token
    if(!$access_token) $access_token = $accessToken; //if cannot be extended then just return the access token with 2 hours expiry
    return $access_token;
}
Kugutsumen
  • 600
  • 1
  • 6
  • 19
  • Tried this... it does give a different token than what was passed but the issued date and expiration date are the same (using the fb debugger). Just thought others would want to know. – ppetree Aug 04 '13 at 22:38
  • @ppetree maybe you are trying to re-extended the already extended access token? I usually pass fresh access token to this function every time the user authenticates. – Kugutsumen Aug 05 '13 at 05:49
  • Problem is, the extended token supposedly expires in 60 days and I don't want the user to have to reauthenticate... that seems very nonsensical. In my case the user is posting to my site and we're posting to fb and tweeting on their behalf. – ppetree Aug 09 '13 at 18:05
0
use Facebook\FacebookSession;
use Facebook\GraphSessionInfo;
use Facebook\FacebookRequest;
use Facebook\GraphUser;
use Facebook\FacebookRequestException;
use Facebook\FacebookRedirectLoginHelper;

    FacebookSession::setDefaultApplication('YOURAPPID', 'SECRET');

    $user_accessToken = $_COOKIE['access_token_facebook']

    $session = new FacebookSession($user_accessToken);

    try {
        $session->validate();
    } catch (FacebookRequestException $ex) {
        // When Facebook returns an error
        echo $ex->getMessage();
    } catch (\Exception $ex) {
        // When validation fails or other local issues
        echo $ex->getMessage();
    }
    if ($session) {
        // Exchange token for long token
        $longToken = $session->getExchangeToken();
        // ... your other stuff
    }

Ref: https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens https://developers.facebook.com/docs/facebook-login/access-tokens#extending

Eduardo Chongkan
  • 752
  • 7
  • 12