2

I'm making a web app using Node.js which has separate login and registration for two roles - "user" and "org".
The basic flow would be :
User
user\registration -> user\login -> dashboard

Org
org\registration -> org\login -> org-dashboard

Since there are two separate authentication cases, I've used two instances of new LocalStrategy.

passport.js

module.exports = function (passport) {
  passport.use(
    "user-local",
    new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
      User.findOne({ email: email })
        .then((user) => {
          if (!user) {
            return done(null, false, {
              message: "That email has not been registered yet!",
            });
          }
          //Match password
          bcrypt.compare(password, user.password, (err, isMatch) => {
            if (err) throw err;
            if (isMatch) {
              return done(null, user);
            } else {
              return done(null, false, { message: "Password Incorrect" });
            }
          });
        })
        .catch((err) => console.log(err));
    })
  );

  passport.use(
    "org-local",
    new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
      Organization.findOne({ email: email })
        .then((user) => {
          if (!user) {
            return done(null, false, {
              message: "That NGO has not been registered yet!",
            });
          }
          //Match password
          bcrypt.compare(password, user.password, (err, isMatch) => {
            if (err) throw err;
            if (isMatch) {
              return done(null, user);
            } else {
              return done(null, false, { message: "Password Incorrect" });
            }
          });
        })
        .catch((err) => console.log(err));
    })
  );

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

  passport.deserializeUser((login, done) => {
    if (login.role === "user") {
      User.findById(login, function (err, user) {
        if (user) done(null, user);
        else done(err, { message: "User not found" });
      });
    } else if (login.role === "org") {
      console.log("here");
      Organization.findById(login, (err, user) => {
        if (user) done(null, user);
        else done(err, { message: "Organization not found" });
      });
    } else {
      done({ message: "No entity found" }, null);
    }
  });
};

However, even though the user login is working fine, I am not able to login through the org\login.

org.js

//Org Login Handle
router.post("/login", (req, res, next) => {
  passport.authenticate('org-local', {
    successRedirect: "/org-dashboard",
    failureRedirect: "/org/login",
    failureFlash: true,
  })(req, res, next);
});

user.js

//User Login Handle
router.post('/login', (req,res, next) =>{
    passport.authenticate('user-local', {
        successRedirect:'/dashboard',
        failureRedirect:'/user/login',
        failureFlash: true
    })(req, res, next);
});

Whenever I login from org\login I noticed, it is going into the user-local authentication strategy. I'm new to Node.js and I referred this to get the code in cases where multiple local strategies.
Please let me know I have to make any changes or I need to add anything else. Thanks.

vnk
  • 1,060
  • 1
  • 6
  • 18
  • in your `/login` route for `org`, can you try passing `next` parameter as well to the `passport.authenticate`, like how you have done for user login route. Also, I noticed that failure route in org case is just `/login`, I thought it should be `/org/login` – Rishabh Gupta Sep 02 '21 at 07:28
  • I did that. But I'm still facing the same issue. It is going to the user-local authentication strategy instead of org-local. – vnk Sep 02 '21 at 08:03
  • you are using `router.post('/login', ...)` for both `user` and `org` login. Here I assumed that these routers are different and they routers for the path `/user` and `/org` respectively. Otherwise the router should be configured as `router.post('/user/login', ...)` and `router.post('/org/login', ...)`. Can you confirm this. – Rishabh Gupta Sep 02 '21 at 08:08
  • Yes. So in app.js I have `const userRouter = require('./routes/user'); app.use('/user', userRouter);` I've done the same for org.js . So there are separate routers. Does this clarify your doubt? – vnk Sep 02 '21 at 08:26
  • Yes, it clarifies my doubt, thanks – Rishabh Gupta Sep 02 '21 at 08:27
  • @RishabhGupta I was able to resolve the issue. Thank you for your help. – vnk Sep 02 '21 at 08:56

1 Answers1

0

I was able to resolve the issue. The form action was being redirected to user\login which is why the wrong local strategy was being called.

vnk
  • 1,060
  • 1
  • 6
  • 18