Search code examples
mongodbsessionoauth-2.0passport.js

How do store multiple Outh2 ids without creating and empty/null string?


I`m trying to create a basic app, where you can register by email/password or by using Google or Facebook Oauth2 saving the necessary in mongoDB. The problem occur when you trying access the app from multiple google or facebook accounts. (500 Internal Server Error) I understand that the problem is that by using Oauth2 I create an empty / null string and in the mongoDB due to indexing (I don't completely understand it) it will result in an error. Please have a look on my code, I took the unnecessary lines out to make it shorter. Here is a screenshot of the DB: DBscreenshot

const userSchema = new mongoose.Schema({
  email: String,
  password: String,
  googleId: String,
  facebookId: String,
  secret: Array
});

userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);

const User = new mongoose.model("User", userSchema);

passport.use(User.createStrategy());

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

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

passport.use(new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "https://app-secret.herokuapp.com/auth/google/secrets",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
  },
  function(accessToken, refreshToken, profile, cb) {
    // console.log(profile);
    User.findOrCreate({
      googleId: profile.id
    }, function(err, user) {
      return cb(err, user);
    });
  }
));

passport.use(new FacebookStrategy({
    clientID: process.env.FACEBOOK_APP_ID,
    clientSecret: process.env.FACEBOOK_APP_SECRET,
    callbackURL: "https://app-secret.herokuapp.com/auth/facebook"
  },
  function(accessToken, refreshToken, profile, cb) {
    User.findOrCreate({
      facebookId: profile.id
    }, function(err, user) {
      return cb(err, user);
    });
  }
));

app.get("/auth/google",
  passport.authenticate('google', {
    scope: ["profile"]
  })
);

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

app.get('/auth/facebook',
  passport.authenticate('facebook'));

app.get('/auth/facebook/secrets',
  passport.authenticate('facebook', {
    failureRedirect: '/login'
  }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/secrets');
  });

app.post("/register", function(req, res) {
  User.register({
    username: req.body.username <----i assume this is the issue as using Oauth2 it will be null
  }, req.body.password, function(err, user) {
    if (err) {
      console.log(err);
      res.redirect("/register")
    } else {
      passport.authenticate("local")(req, res, function() {
        res.redirect("/secrets")
      })
    }
  })
});

Solution

  • Although its not a "elegant" way but eventually i overcome by the problem to allocate a variable to the usernames even if they didnt need to have one as they were using Oauth.. Like this the string wont be empty or null so mongoDB eventually let more users register from both google and facebook.