passport-facebook: FacebookTokenError
I have been using passport-facebook in my app for many months now, and just now I have run into this issue. I sort of understand what this issue means, but I am confused as to why its just now happening and how to fix it. I noticed someone else mention a similar issue and they just forgot to call done() in their auth handler. I double checked my auth handler to make sure I was calling it, and sure enough, I am calling it. I did recently upgrade to using Express4, and I am using the latest version of passport 0.2.0. Any help or direction on where to look would be appreciated. Thanks!
Passport-Facebook Error:
FacebookTokenError: This authorization code has been used.
at Strategy.parseErrorResponse (/mnt/data/1/node_modules/passport-facebook/lib/strategy.js:198:12)
at Strategy.OAuth2Strategy._createOAuthError (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:345:16)
at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:171:43
at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:177:18
at passBackControl (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:124:9)
at IncomingMessage.<anonymous> (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:143:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:929:16
at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
Metadata:
[32mstack: [39m
[32m- [39mFacebookTokenError: This authorization code has been used.
[32m- [39m at Strategy.parseErrorResponse (/mnt/data/1/node_modules/passport-facebook/lib/strategy.js:198:12)
[32m- [39m at Strategy.OAuth2Strategy._createOAuthError (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:345:16)
[32m- [39m at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:171:43
[32m- [39m at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:177:18
[32m- [39m at passBackControl (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:124:9)
[32m- [39m at IncomingMessage.<anonymous> (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:143:7)
[32m- [39m at IncomingMessage.emit (events.js:117:20)
[32m- [39m at _stream_readable.js:929:16
[32m- [39m at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
[32m- [39m at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
[32mname: [39m FacebookTokenError
[32mmessage: [39mThis authorization code has been used.
[32mtype: [39m OAuthException
[32mcode: [39m [34m100[39m
[32mstatus: [39m [34m500[39m
FacebookTokenError: This authorization code has been used.
at Strategy.parseErrorResponse (/mnt/data/1/node_modules/passport-facebook/lib/strategy.js:198:12)
at Strategy.OAuth2Strategy._createOAuthError (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:345:16)
at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/lib/strategy.js:171:43
at /mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:177:18
at passBackControl (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:124:9)
at IncomingMessage.<anonymous> (/mnt/data/1/node_modules/passport-facebook/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:143:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:929:16
at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
at /mnt/data/1/node_modules/newrelic/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:177:31
My auth handler:
exports.setupFacebookAuth = function setupFacebookAuth() {
this.passport.use(new FacebookStrategy({
clientID: config.FACEBOOK_APP_ID,
clientSecret: config.FACEBOOK_APP_SECRET,
callbackURL: config.FACEBOOK_callbackURL,
passReqToCallback: true,
}, function(req, accessToken, refreshToken, profile, done) {
process.nextTick(function() {
if (profile.hasOwnProperty('emails') && profile.emails.length > 0) {
var userData = {
email: profile.emails[0].value,
method: 'facebook',
id: profile.id,
mixpanelID: null
};
//check to see if we have a mixpanel cookie
if (req.cookies.hasOwnProperty('mp_userID') && req.cookies.mp_userID) {
userData.mixpanelID = JSON.parse(req.cookies.mp_userID).distinct_id;
}
var query = Account.findOne()
.where('email').equals(userData.email);
if (!req.session.signup) {
query.where('facebookID').equals(userData.id);
}
query.execQ()
.then(function(account) {
if (account && !req.session.signup) {
userData.mixpanelID = account.mixpanelID || userData.mixpanelID;
if (config.EnableMixpanel) {
mixpanel.track("login", {
distinct_id: account.mixpanelID,
method: 'facebook',
location: config.mixPanelLocation
});
mixpanel.people.increment(account.mixpanelID, "facebook");
mixpanel.people.set(account.mixpanelID, "last_login", new Date());
}
var resaveAccount = false;
if (!account.facebookID) {
account.facebookID = userData.id;
resaveAccount = true;
}
if (!account.mixpanelID) {
account.mixpanelID = userData.mixpanelID;
resaveAccount = true;
}
if (resaveAccount) {
account.saveQ();
}
userData.accountID = account._id;
return done(null, userData);
} else {
return done(null, userData, {
message: 'No Account Exists'
});
}
})
.fail(function(err) {
return done(err, null);
})
.done();
} else {
done(null, false, {
message: 'No Email Associated'
});
}
});
}));
};
My routes:
router.route('/facebook/return*')
.get(function(req, res, next) {
passport.authenticate('facebook', function(err, user, info) {
return LogUserIn(req, res, next, err, user, info);
})(req, res, next);
});
//facebook login url
router.route('/facebook*')
.get(passport.authenticate('facebook', {
scope: 'email'
}));
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 3
- Comments: 31
I’m late to the party but was pulling my hair out for a good while over this. I eventually figured out what was happening though.
Basically, both route handlers (the primary one and the callback one) were being hit on the Facebook callback.
I had configured them as:
Unfortunately, I didn’t realize that both route handlers were being triggered when the call to
/facebook/callbackwas made. This basically passed the request throughpassport.authenticatetwice.Reworking the route definitions fixed this issue for me (basically reordering them since I end the response in the
callbackroute handler).Hopefully this helps someone who runs into this 😄
What solved it for me was enabling enableProof: true in the strategy.
hope it helps.
Hello all { @toddbluhm, @maxmert, @daxsorbito @lefnire et al }
I have a REST api in Express that uses a Sessionless Facebook Login using the info from Jeroen Pelgrims. What it does is:
What passport-facebook authenticate uses in the callback-page is this:
passport.authenticate(‘strategy’, options, user, error)The behavior is correctly throwing that error! As @jsilveira said in the comments, the error happens if a user logs in twice…
My answer is very simple, I catch the error… Read on there is a but…
// route for facebook authentication and login router.get('/auth/facebook', passport.authenticate('facebook', {session: false, scope : ['email'] }) ); // handle the callback after facebook has authenticated the user router.get('/auth/facebook/callback', passport.authenticate('facebook', { session: false, failureRedirect : '/'}), // on succes function(req,res) { // return the token or you would wish otherwise give eg. a succes message res.render('json', {data: JSON.stringify(req.user.access_token)}); }, // on error; likely to be something FacebookTokenError token invalid or already used token, // these errors occur when the user logs in twice with the same token function(err,req,res,next) { // You could put your own behavior in here, fx: you could force auth again... // res.redirect('/auth/facebook/'); if(err) { res.status(400); res.render('error', {message: err.message}); } } );But, if you guys want it to just log in/authorize again you could insert a callback or redirect in the error part.
Hope this clarifies some issues you guys are having. If you by any chance have questions or requests, dont be shy. Info is on my profile.
PS: stackoverflow.com has an answer for re-auth it follows like this:
I’m having the same issue. From several tests I’ve made, I realized this is happening when some users click twice on the facebook login button. What I don’t understand is why passport-facebook is throwing the error instead of forwarding it to the callback handler. Any ideas?
Hello Friends, I faced the same issue in my app. It happens because of errors in facebook callback function. When i faced this issue I invoked done(null,profile) directly. it worked and it redirect to the appropriate URL after successfully logging in. But when invoked the done function inside the query function then it gave this error. So try invoking the done(null,profile); directly without querying though the db.If it works for you then it clearly indicates that there is an error in the code before invoking the done function. Then try to fix the error and then invoke the done function.
`passport.use({ clientId:" -----“,clientSecret:”-----",callbackURL:“http://localhost:PORT/auth/facebook/callback”}, (accessToken,refreshToken,profile,done)=>{
//check your console you will find the accessToken and refresh Tokens console.log(“Your accessToken is :”+accessToken); console.log(“Your refreshToken is :”+refreshToken ); done(null,profile);
});`
Same issue… How can i solve this?
@rocketspacer I’m using v4
If you happen to do
app.use('auth/facebook', passport.authenticate(...)instead ofapp.get, then you would end up with the routes passing through.I just wanted to point out what was going on in my particular implementation since it was not immediately clear and was resolved by reordering my routes so that they were hit in the correct order.
@flaviolivolsi and @Connoropolous Seen it here. https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof
I have it activated in my app. So it assumed the second call on that auth code was a “bad guy”.
Well I am sorry to say that I have made no progress on this issue. Partially due to time, but also because we have such a small amount of users that use facebook on our site, I have not run into this issue for a while. I still believe it exists, but no solution yet. It might be best for others to just go the same route as https://github.com/HabitRPG/habitrpg/issues/4221 and just integrate directly with the facebook js sdk.
Same issue. Didn’t figure out yet.