Thuan Nguyen
Thuan Nguyen

Reputation: 886

Google OAuth Nodejs handle error using passport, passport-google-oauth20

I'm writing authentication Nodejs API using passport, passport-google-oauth20

Everything is work but the problem is now I want to verify email of the user via domain. My system just allows email with domain @framgia.com can log in to. If not, send the user back a message.

My code here:

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

const mongoose = require('mongoose');
const keys = require('../config/keys');

const User = mongoose.model('users');

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  User.findById(id).then(user => {
    done(null, user);
  })
});

passport.use(
  new GoogleStrategy(
    {
      clientID: keys.googleClientID,
      clientSecret: keys.googleClientSecret,
      callbackURL: '/auth/google/callback',
    },
    async (accessToken, refreshToken, profile, done) => {

      const existingUser = await User.findOne({ googleId: profile.id });
      if (existingUser) {
        return done(null, existingUser);
      }

      if (!profile._json.domain || profile._json.domain !== 'framgia.com') {
        return done(null, {error: 'Not allow access!'});
      }

      const user = await new User({
        googleId: profile.id,
        email: profile.emails[0].value,
        name: profile.displayName,
        avatar: profile.photos[0].value,
      }).save();

      done(null, user);
    },
  ),
);

And I'm writing logic code like that:

if (!profile._json.domain || profile._json.domain !== 'framgia.com') {
    return done(null, {error: 'Not allow access!'});
}

But I think it won't work, but I don't know how to handle the error and send the message back to user.

My routes:

const passport = require('passport');

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

  app.get(
    '/auth/google/callback',
    passport.authenticate('google', { failureRedirect: '/login' }),
    (req, res) => {
      // Successful authentication, redirect home.
      res.redirect('/');
    },
  );
};

How to handle the error and redirect to route /error with some message?

Any ideas would be greatly appreciated, thanks.

Upvotes: 0

Views: 1918

Answers (1)

zerosand1s
zerosand1s

Reputation: 750

First of all, if you want to return the user only if an email has a certain domain, you need to put your domain check logic before findOne(). With current logic, if you found a user it will simply return it without checking the email domain

//check email domain before finding the user

if (!profile._json.domain || profile._json.domain !== 'framgia.com') {
  return done(null, {error: 'Not allow access!'});
}

const existingUser = await User.findOne({ googleId: profile.id });
if (existingUser) {
  return done(null, existingUser);
}

According to passport js documentation, http://www.passportjs.org/docs/configure/ (check verify callback section)

An additional info message can be supplied to indicate the reason for the failure. This is useful for displaying a flash message prompting the user to try again.

so if the domain does not match, you should return an error like this

return done(null, false, { message: 'Not allow access!' });

Upvotes: 2

Related Questions