The client for my web-app wants to totally separate regular users and admins, hence I'm trying to implement two local strategies for passport.js
:
passport.use('local', new LocalStrategy({
usernameField: 'email'
}, function(email, password, done) {
User.findOne({ email: email }, function(err, user) {
if (err) return done(err);
if (!user) return done(null, false, { message: 'Wrong email or password.' });
if (!user.validPassword(password)) return done(null, false, { message: 'Wrong email or password.' });
done(null, user);
});
}));
passport.use('admin', new LocalStrategy({
usernameField: 'email'
}, function(email, password, done) {
Admin.findOne({ email: email }, function(err, admin) {
if (err) return done(err);
if (!admin) return done(null, false, { message: 'Wrong email or password.' });
if (!admin.validPassword(password)) return done(null, false, { message: 'Wrong email or password.' });
done(null, admin);
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
Admin.findById(id, function(err, admin) {
if (err) return done(err);
if (admin) return done(null, admin);
User.findById(id, function(err, user) {
done(err, user);
});
});
});
And then in my API admin router:
router.post('/', function(req, res, next) {
if (typeof req.body.email === 'undefined') return res.json({ success: false, message: 'Email not supplied.' });
if (!validator.isEmail(req.body.email)) return res.json({ success: false, message: 'Wrong email format.' });
if (typeof req.body.password === 'undefined') return res.json({ success: false, message: 'Password not supplied.' });
if (req.body.password.length === 0) return res.json({ success: false, message: 'Password not supplied.' });
passport.authenticate('admin', function(err, admin, info) {
if (!admin) return res.json({ success: false, message: info.message });
req.logIn(admin, function(err) {
if (err) return res.json({ success: false, message: 'Server error.', reason: err });
console.log('user:');
console.log(req.user); // both users and admins go here
console.log('admin:');
console.log(req.admin); // undefined
res.json({ success: true });
});
})(req, res, next);
});
In fact, I was following the answer here: https://stackoverflow.com/a/21898892/1830420, and Matthew Payne gets two session variables: req.user
and req.sponsor
. In my case, even if an admin authenticates, it gets written to req.user
. Now, trying to implement my client's desire of totally separating users and admins, I want to get req.user
and req.admin
, but every time it gets written to req.user
. I thought changing LocalStrategy name would help, but passport.js
seems to ignore both the strategy name and model name.
Any help is very much appreciated.
P.S. I know I can have everyone in User
model and write some middleware to protect certain routes based on roles, but then again, unfortunately, I don't get to choose here.
Unfortunately you can't do that with Passport. You will need to create express middleware to handle admin authentication.