passport-google-oauth2: TokenError: Code was already redeemed and TokenError: Bad Request

I have a pretty basic passport setup as you can see below. Every once in a while I get two different errors. TokenError: Code was already redeemed and TokenError: Bad Request for reasons I cannot seem to find.

I’ve looked around a lot (1 week) for possible solutions but am yet to find one which works.

Do you see anything wrong with the current code?

app.get('/auth/google', redirect, passport.authenticate('google', { scope: ['profile', 'email'] }));

app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/' }),
  function(req, res) {
    res.redirect('/');
  }
);

Here are the two errors:

TokenError: Bad Request 
  at Strategy.OAuth2Strategy.parseErrorResponse (/app/node_modules/passport-oauth2/lib/strategy.js:320:12) 
  at Strategy.OAuth2Strategy._createOAuthError (/app/node_modules/passport-oauth2/lib/strategy.js:367:16) 
  at /app/node_modules/passport-oauth2/lib/strategy.js:166:45 
  at /app/node_modules/oauth/lib/oauth2.js:177:18 
  at passBackControl (/app/node_modules/oauth/lib/oauth2.js:123:9) 
  at IncomingMessage.<anonymous> (/app/node_modules/oauth/lib/oauth2.js:143:7) 
  at emitNone (events.js:85:20) 
  at IncomingMessage.emit (events.js:179:7) 
  at endReadableNT (_stream_readable.js:913:12) 
  at _combinedTickCallback (internal/process/next_tick.js:74:11) 
  at process._tickCallback (internal/process/next_tick.js:98:9)



TokenError: Code was already redeemed. 
      at Strategy.OAuth2Strategy.parseErrorResponse (/app/node_modules/passport-oauth2/lib/strategy.js:320:12) 
      at Strategy.OAuth2Strategy._createOAuthError (/app/node_modules/passport-oauth2/lib/strategy.js:367:16) 
      at /app/node_modules/passport-oauth2/lib/strategy.js:166:45 
      at /app/node_modules/oauth/lib/oauth2.js:177:18 
      at passBackControl (/app/node_modules/oauth/lib/oauth2.js:123:9) 
      at IncomingMessage.<anonymous> (/app/node_modules/oauth/lib/oauth2.js:143:7) 
      at emitNone (events.js:85:20) 
      at IncomingMessage.emit (events.js:179:7) 
      at endReadableNT (_stream_readable.js:913:12) 
      at _combinedTickCallback (internal/process/next_tick.js:74:11) 
      at process._tickCallback (internal/process/next_tick.js:98:9) 

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 8
  • Comments: 34

Most upvoted comments

you have to specify the full url in the callbackURL section of the strategy: for example: when i’m running my code locally on localhost:3000 with code like this:

passport.use(new googleStrategy({

	clientID:keys.clientID,
	clientSecret:keys.clientSecret,
	callbackURL:'auth/google/callback'
},(accessToken,refreshToken, profile,done)=>{

	console.log(accessToken);
	console.log(refreshToken);
	console.log(profile);
}
));

app.get('/auth',passport.authenticate('google',{

	scope:['profile','email']
}));

app.get('/auth/google/callback', 
  passport.authenticate('google'));

The above code will surely throw an error like token:Bad request. so you have pass the complete URl so the final code will be:

passport.use(new googleStrategy({

	clientID:keys.clientID,
	clientSecret:keys.clientSecret,
	callbackURL:'http://localhost:3000/auth/google/callback'
},(accessToken,refreshToken, profile,done)=>{

	console.log(accessToken);
	console.log(refreshToken);
	console.log(profile);
}
));

app.get('/auth',passport.authenticate('google',{

	scope:['profile','email']
}));

app.get('/auth/google/callback', 
  passport.authenticate('google'));

After a bit of digging, it looks like failureRedirect is ONLY used for strategy ‘failures’ and not ‘errors’, which is what gets thrown if a Token has already been used/redeemed.

This is a bit confusing, I agree.

It’s almost as if passport needs an additional option for ‘errorRedirect’

You can handle this outside of passport by implementing your own error handling. For example:

app.get('/auth/google/callback',
  passport.authenticate('google'), // complete the authenticate using the google strategy
  (err, req, res, next) => { // custom error handler to catch any errors, such as TokenError
    if (err.name === 'TokenError') {
     res.redirect('/auth/google'); // redirect them back to the login page
    } else {
     // Handle other errors here
    }
  },
  (req, res) => { // On success, redirect back to '/'
    res.redirect('/');
  }
);

someone please give a solution to that problem i have tried almost everything on internet but that shit just fails to work in the deployment(only google cloud) even though it works fine on other cloud platform and even on localhost

After reviewing the other passport strategy examples (GitHub), I think what is missing is the done callback in the passport callback, like this:

passport.use(
  new GoogleStrategy(
    {
      clientID: config.google.clientID,
      clientSecret: config.google.clientSecret,
      callbackURL: '/auth/google/redirect'
    },
    function(accessToken, refreshToken, profile, done) {
      new User({
        username: profile.username,
        providerId: profile.id,
        provider: 'Google'
      })
        .save()
        .then((user) => {
          console.log({ user });
          done(null, user); //callback to let passport know that we are done processing
        });
    }
  )
);

Try inspecting the TokenError (in my case the code property was helpful). If you’re using express and errorHandler you can get some additional detail by manually logging the error:

  app.use(errorHandler({ log: errorNotification }));

  function errorNotification(err, str, req) {
    console.log('ERROR', err);
  }

This allowed me to see the code property (redirect_uri_mismatch) which helped me determine the actual issue.

ERROR! { TokenError: Bad Request at Strategy.OAuth2Strategy.parseErrorResponse (/home/ec2-user/environment/revtm/node_modules/passport-oauth2/lib/strategy.js:345:12) at Strategy.OAuth2Strategy._createOAuthError (/home/ec2-user/environment/revtm/node_modules/passport-oauth2/lib/strategy.js:394:16) at /home/ec2-user/environment/revtm/node_modules/passport-oauth2/lib/strategy.js:172:45 at /home/ec2-user/environment/revtm/node_modules/oauth/lib/oauth2.js:191:18 at passBackControl (/home/ec2-user/environment/revtm/node_modules/oauth/lib/oauth2.js:132:9) at IncomingMessage.<anonymous> (/home/ec2-user/environment/revtm/node_modules/oauth/lib/oauth2.js:157:7) at IncomingMessage.emit (events.js:187:15) at endReadableNT (_stream_readable.js:1081:12) at process._tickCallback (internal/process/next_tick.js:63:19) name: ‘TokenError’, message: ‘Bad Request’, code: ‘redirect_uri_mismatch’, uri: undefined, status: 500 }

Hello all,

I had the same issue, and it got fixed once I removed the absolute path from the callbackURL in passport setup

    passport.use(new Strategy({
        clientID: GOOGLE_CLIENT_ID,
        clientSecret: GOOGLE_CLIENT_SECRET,
        callbackURL: `/api/${API_VERSION}/auth/google/callback`,
        passReqToCallback: true
    }

instead of

 callbackURL: `http://localhost:4000/api/${API_VERSION}/auth/google/callback`

Hopefully this will help at least some of you

I am getting only first error: TokenError: Bad Request

I have no idea what to do.

For me the problem was with final req handler, res.redirect(‘#/after-auth’); was casing this error.

router.get('/google/callback',
    passport.authenticate('google', { failureRedirect: '/login' }),
    function (req, res) {
        res.redirect('#/after-auth');
    }
);

changing to res.redirect(‘/#/after-auth’); helped.

router.get('/google/callback',
    passport.authenticate('google', { failureRedirect: '/login' }),
    function (req, res) {
        res.redirect('/#/after-auth');
    }
);

passport.use( new GoogleStrategy({ clientID: “" clientSecret: "”, callbackURL: ‘http://localhost:5000/auth/google/callback’, proxy: true, }, (accessToken, refressToken, profile, done) => { //your code stuff. }), )