Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Passport.js GoogleStrategy not working! Getting error "Cannot read properties of undefined (reading '0')"

I am trying to implement passport.js google login, but as you can see in my code below I am having an issue with the profile object which is not behaving like the documentation says it should. Please help.

Also, I do not wish to you passports build in session support! I have my own functions for creating sessions and authenticating if the user is logged in.

const passport = require('passport');
const GoogleStrategy = require('passport-google-oidc');
const User = require('../models/user-schema');

async function create_user(name, email) {
  // too long to show, just assume it works (not relevant for my question anyways)
  const user = await User.create({});
  return login_user(user)
}

function login_user(user) {
  req.session.user_id = user._id;
  delete user._doc.hash;
  delete user._doc.salt;
  return user;
}

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SEC,
  callbackURL: 'http://localhost:4000/auth/login-google/redirect/',
  scope: [ 'email', 'profile' ]
},
async function(request, accessToken, refreshToken, profile, done) {
  try {
    console.log(profile); // Gives a long string for some reason
    console.log(profile.id); // Gives undefined even though it is used in the documentation 
    const email = profile.emails[0].value; // Here it throws the error even though this is what I have seen others use 

// (!)   
// Everything beyond this point I havent had the chance to test yet because the profile object, well I guess, ISNT AN OBJECT!
// (!)

    const existing_user = await User.findOne({ email: email });
    const user = (existing_user) ? login_user(existing_user) : await create_user(profile.displayName, email);
    return done(null, user);
  }
  catch (err) {
    console.log('errror: ' + err.message);
    return done(err);
  }
}));

router.get('/login-google', passport.authenticate('google'));

router.get('/login-google/redirect/', passport.authenticate('google', {
  successRedirect: '/login-google/success',
  failureRedirect: '/login-google/failure'
}));

router.get('/login-google/success', (req, res) => {
  console.log('success');
});

router.get('/login-google/failure', (req, res) => {
  console.log('failure');
});

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You’re importing GoogleStrategy from passport-google-oidc which has a different signature. The current signature of your implementation belongs to GoogleStrategy from passport-google-oauth2.

According to the passport’s documentation for passport-google-oidc, your function’s signature should be something like this:

var GoogleStrategy = require('passport-google-oidc');

passport.use(new GoogleStrategy({
    clientID: process.env['GOOGLE_CLIENT_ID'],
    clientSecret: process.env['GOOGLE_CLIENT_SECRET'],
    callbackURL: 'https://www.example.com/oauth2/redirect'
  },
  function verify(issuer, profile, cb) {
    db.get('SELECT * FROM federated_credentials WHERE provider = ? AND subject = ?', [
      issuer,
      profile.id
    ], function(err, cred) {
      if (err) { return cb(err); }
      if (!cred) {
        // The account at Google has not logged in to this app before.  Create a
        // new user record and associate it with the Google account.
        db.run('INSERT INTO users (name) VALUES (?)', [
          profile.displayName
        ], function(err) {
          if (err) { return cb(err); }

          var id = this.lastID;
          db.run('INSERT INTO federated_credentials (user_id, provider, subject) VALUES (?, ?, ?)', [
            id,
            issuer,
            profile.id
          ], function(err) {
            if (err) { return cb(err); }
            var user = {
              id: id.toString(),
              name: profile.displayName
            };
            return cb(null, user);
          });
        });
      } else {
        // The account at Google has previously logged in to the app.  Get the
        // user record associated with the Google account and log the user in.
        db.get('SELECT * FROM users WHERE id = ?', [ cred.user_id ], function(err, user) {
          if (err) { return cb(err); }
          if (!user) { return cb(null, false); }
          return cb(null, user);
        });
      }
    }
  })
));
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading