Search code examples
node.jsreactjspassport.jspassport-google-oauth

TokenError: Bad Request at Strategy.OAuth2Strategy.parseErrorResponse


I'm getting this error when I choose an account in google login page, after choosing an account (Yes the same account I chose in Google Cloud) I get this error instead of console logging the profile!

TokenError: Bad Request

at Strategy.OAuth2Strategy.parseErrorResponse (/Users/ /my-blog/api/node_modules/passport-oauth2/lib/strategy.js:373:12)
at Strategy.OAuth2Strategy._createOAuthError (/Users/  /my-blog/api/node_modules/passport-oauth2/lib/strategy.js:420:16)
at /Users/  /my-blog/api/node_modules/passport-oauth2/lib/strategy.js:177:45
at /Users/  /my-blog/api/node_modules/oauth/lib/oauth2.js:191:18
at passBackControl (/Users/  /my-blog/api/node_modules/oauth/lib/oauth2.js:132:9)
at IncomingMessage.<anonymous> (/Users/  /my-blog/api/node_modules/oauth/lib/oauth2.js:157:7)
at IncomingMessage.emit (node:events:532:35)
at endReadableNT (node:internal/streams/readable:1346:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)

My PassportJs Setup:

const User = require("./models/User");
const mongoose = require("mongoose");

const GoogleStrategy = require("passport-google-oauth20").Strategy;

module.exports = function (passport) {
    passport.use(
      new GoogleStrategy(
        {
          clientID: "",
          clientSecret: "",
          callbackURL: "api/auth/google/callback",
        },
        async (accessToken, refreshToken, profile, done) => {
            console.log(profile)
        }
      )
    )
  
    passport.serializeUser((user, done) => {
      done(null, user.id)
    })
  
    passport.deserializeUser((id, done) => {
      User.findById(id, (err, user) => done(err, user))
    })
  }

Here it should console logging the profile from google!

My Auth.js:

const passport = require("passport");

router.get("/google", passport.authenticate("google", { scope: ["profile"] }))

router.get(
  '/google/callback',
  passport.authenticate('google', { failureRedirect: '/' }),
  (req, res) => {
    res.redirect('/register')
  }
)

My index.js:

const authRoute = require("./routes/auth");
const passport = require ("passport");
// Passport config
require('./passport')(passport);

const session = require('express-session')

// Sessions
app.use(
    session({
      secret: 'keyboard cat',
      resave: false,
      saveUninitialized: false
    })
  )
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());

app.use("/api/auth", authRoute);

app.listen("4000", () => {
    console.log("Backend is running.");
});

Google Cloud: enter image description here

I just want the profile that returned from google to show in my console log.


Solution

  • This is how I solved it. Firstly you need to add your clientID and clientSecret, you can do that here on the credentials page.

    After setting that, your code should look like this:

    passport.use(
      new GoogleStrategy(
        {
          clientID: "YOUR CLIENT-ID",
          clientSecret: "YOUR CLIENT-SECRET",
          callbackURL: "api/auth/google/callback",
        },
        async (accessToken, refreshToken, profile, done) => {
            console.log(profile)
        }
      )
    )
    
     
    

    then your callbackURL should include your API baseUrl, for me, it is:

          callbackURL: "http://5000/api/auth/google/callback",
    

    Also, your Authorized redirect URIs, your sign-in button and your callbackURL have to share the same URL, otherwise, two cookies will be created and it will lead to losing your session

    this is what my login button looks like:

    <button>
        <a href="http://localhost:5000/api/auth/google/callback" >Login with Google</a>
    </button>
    

    this should work perfectly well, you should see your profile on your console