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

huangapple go评论71阅读模式
英文:

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 as the documentation says it should. Please help.

Also, I do not wish to use Passport's built-in session support! I have my own functions for creating sessions and authenticating if the user is logged in.

英文:

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');
});

答案1

得分: 1

您正在从passport-google-oidc中导入GoogleStrategy,但它具有不同的签名。您当前实现的签名属于passport-google-oauth2中的GoogleStrategy

根据passport-google-oidc的passport文档,您的函数签名应该类似于以下内容:

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) {
        // Google帐户以前未登录到此应用程序。创建一个新的用户记录并与Google帐户关联。
        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 {
        // Google帐户先前已登录到应用程序。获取与Google帐户关联的用户记录并登录用户。
        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);
        });
      }
    }
  })
));
英文:

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);
        });
      }
    }
  })
));

huangapple
  • 本文由 发表于 2023年1月4日 01:00:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/74996375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定