passport-facebook icon indicating copy to clipboard operation
passport-facebook copied to clipboard

exchange token for long lived token

Open gad2103 opened this issue 10 years ago • 8 comments

is there a way to do this with passport? i am currently using passport to get the access token and then using node-facebook-sdk to exchange the token for a longer lived token. however, for some reason when i try to save the new token to the database and return it to the client, the old token is still passed back and the database doesn't show any updates. here are my routes:

var router = express.Router();

router
  .get('/',  passport.authenticate('facebook', {
    scope: ['email', 'user_about_me', 'read_stream', 'publish_actions', 'user_likes'],
    failureRedirect: '/signup',
    session: false
  }))

  .get('/callback', auth.bindUserToReq(), passport.authenticate('facebook', {
    failureRedirect: '/signup',
    session: false
  }), auth.extendTokenLife('facebook'), auth.setTokenCookie);

and the extendTokenLife function:

/**
 * Extend access token
 */
function extendTokenLife(provider) {
    return compose()
    .use(function(req,res,next){
        var access_token = req.user.strategies[provider].token;
        console.log('inside of extending the life ' + access_token);
        if (provider === 'facebook') {
            FB.api('oauth/access_token', {
                client_id: config[provider].clientID,
                client_secret: config[provider].clientSecret,
                grant_type: 'fb_exchange_token',
                fb_exchange_token: access_token
            }, function(res) {
                if (!res || res.error) {
                    console.log(!res ? 'could not extend ' + provider + 'token' : res.error);
                    return next(); // TODO change this to a usable response that will show up on the client side aka not sure how we are handling errors in this app yet!
                }
                console.log('new access token granted for long life');
                console.log(res.access_token);
                User.findById(req.user._id, function(err,db_user){
                    if(err) return next(err);
                    if(!db_user) return res.send(403);

                    db_user.strategies[provider].token = res.access_token;
                    console.log('CHANGING USER STRATEGY TOKEN BEFORE SAVING TO ' + db_user.strategies[provider].token);
                    db_user.save(function(err) {
                        if(err) {
                            return next(err);
                        } else {
                            console.log('saved new token apparently to ' + db_user.name);
                            return next();
                        }
                    });
                });
            });
        }
    });
}

the logs make it look like everything is working fine but the database shows nothing. furthermore, my final middleware function shows the old token too.

i need to be able to exchange the token.

NOTE: i am using this to connect facebook to a user account that uses a local strategy. not sure if this is part of the problem.

any help would be awesome! thank you.

gad2103 avatar Sep 10 '14 06:09 gad2103

Check this.

After doing the above you will obtain a new short-lived token and then you need to perform the same exchange for a long-lived token as above. In some cases, this newer long-lived token might be identical to the previous one, but we can't guarantee it and your app shouldn't depend upon it.

Page Access Token – These access tokens are similar to user access tokens, except that they provide permission to APIs that read, write or modify the data belonging to a Facebook Page. To obtain a page access token you need to start by obtaining a user access token and asking for the manage_pages permission. Once you have the user access token you then get the page access token via the Graph API.

The answer would be that you have to use Graph API so you are doing it right but you have to call GET /{user-id}/accounts to get the right token. I haven't try that so I hope I'm right. Also check this module.

xpepermint avatar Sep 28 '14 14:09 xpepermint

I'm having the same issue....does no one use passport.js facebook strategy? I would of thought this issue would be resolved by now.

dman777 avatar Mar 29 '16 19:03 dman777

The lifetime of tokens is a policy of Facebook. It's not something this strategy can change. All this strategy does is give you the token.

jaredhanson avatar Mar 29 '16 19:03 jaredhanson

Can the strategy be modified/written to retrieve a long lived token?

If the intent of this strategy is to allow facebook session, can it be stated that this strategy is broken in the read me? Out of the box, I can not achieve a login session with facebook using the passport.js facebook strategy. I'm sure it worked before the short lived tokens came along, but it does not work now. That is the end result when using passport facebook strategy of today.

dman777 avatar Mar 29 '16 19:03 dman777

The strategy is not broken. The intent of this strategy is to authenticate the user, and provide you with the user details and the access token provided by Facebook. Managing the lifetime of tokens is out of scope of this module.

Read this documentation on Facebook: https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension

If you want longer lived tokens, it is the responsibility of your app to manage the lifetime according to Facebook's requirements.

jaredhanson avatar Mar 29 '16 19:03 jaredhanson

I have the feeling that long-lived access tokens are ALREADY being returned right now by Passport. Try this link to verify it:

https://developers.facebook.com/tools/debug/accesstoken/?q=

I am feeding it access tokens that I receive after Facebook authentication using Passport, and they are long-lived.

Maybe something has changed?

mercmobily avatar May 25 '17 03:05 mercmobily

Updates on this?

kevin-coelho avatar Apr 24 '18 00:04 kevin-coelho

This works at least as of release 2.1.1. I recommend closing this (old) thread. Details follow.

@dman777, @gad2103 - I had the same concern. Found THIS thread - thanks for creating it.

@mercmobily is 100% correct (thanks for saving me some time!). Here's what his referenced link returns for the token just returned with passport-facebook:

App ID | 40646652284XYZ : Token of Trust
-- | --
Type | User
App-Scoped User IDLearn More | <123272772> : Darrin User last installed this app via API N/A
Issued | 1531416652 (37 minutes ago)
Expires | 1536600652 (in about 2 months)
Valid | True
Origin | Web
Scopes | user_location, user_friends, email, public_profile

Note: some identifiers changed above to protect the innocent.

So - this seems works out of the box - retrieving long lived access tokens as far as I can tell. My guess is that the request to get the new token just returns the original token since it's already long lived.

@jaredhanson thanks so much for all your hard work! Please let me know where to send the beverage of your choice... ;)

darrin avatar Jul 12 '18 18:07 darrin