My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

I'm trying to implement user authentication with passport-google-oauth20 in Nodejs /Expressjs app

Emmanuel's photo
Emmanuel
·Jun 13, 2017

I want to add the ability for users to be able to create accounts in an express app with their google credentials. So far the user object is only created in mongodb; but after that, the code below, which is supposed to authenticate the user and complete the sign up, results in a failure and I get redirected to the failure route instead of the home page:

router.get('/google/return',
  passport.authenticate('google', { failureRedirect: '/failed' }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/');
  });

After the user is created, however, I'm perfectly able to sign in with the google account that was used in creating the mongodb object.

I'm wondering, perhaps, if this problem is because Google no longer allows OAuth requests to Google in web view. If so, can anyone point me to the better way to handle the google user sign up and authentication in expressjs/node? I have applied this exact same code and concept with passport-facebook, and it works perfectly.

Below is the rest of the code:

app.js

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

const User = require('./models/user');

function generateOrFindUser(accessToken, refreshToken, profile, done){
  if(profile.emails[0]) {
    User.findOneAndUpdate(
      { email: profile.emails[0].value },
      {
        firstName: profile.displayName || profile.username,
        email: profile.emails[0].value,
        profilePhoto: profile.photos[0].value
      },
      {
        upsert: true
      },
      done
      );
   } else {
      var noEmailError = new Error("Your email privacy settings prevent you 
       from signing in.");
      done(noEmailError, null);
     }
}


passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/return",
    profileFields: ['id', 'displayName', 'photos', 'email']
  },
  generateOrFindUser)
);

passport.serializeUser(function(user, done){
  done(null, user._id);
});
passport.deserializeUser(function(userId, done){
  User.findById(userId, done);
});

auth.js

router.get('/login/google',
  passport.authenticate('google', { scope: 
['https://www.googleapis.com/auth/userinfo.email', 
'https://www.googleapis.com/auth/userinfo.profile',
  'https://www.googleapis.com/auth/plus.login',
  'https://www.googleapis.com/auth/plus.me'] }));

//GET /auth/google/return
router.get('/google/return',
  passport.authenticate('google', { failureRedirect: '/failed' }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/');
  });

Everything seems to work fine, except for when a user were to be signing up for the first time; instead of redirecting to the home page (which would mean a success, it takes me to the failed route, so it's failing somewhere; but it's strange cause the user is getting created, the user is just not getting signed in. Any pointers, or observations, pls?