I need two instances of a passport local strategy ("localA" and "localB"), one instance of this authenticates against a collection "colA" in "DbA" and is used in one route sequence (Route A), the other instance authenticates against another collection (ColB) in "DbB" and is used in a second route sequence (Route B).
In both cases, access to "req.user" is needed. In the first route, "req.user" has its expected defined value, however, in the second route, "req.user" is undefined. Here is an extract of what I believe to be the relevant code:
const userA = DbA.model(`colA`, userASchema);
passport.use(`localA`, new passportLocalStrategy({usernameField: `email`, passwordField: `password`}, userA.authenticate()));
passport.serializeUser(userA.serializeUser());
passport.deserializeUser(userA.deserializeUser());
const userB = DbB.model(`colB`, userBSchema);
passport.use(`localB`, new passportLocalStrategy({usernameField: `email`, passwordField: `password`}, userB.authenticate()));
passport.serializeUser(userB.serializeUser());
passport.deserializeUser(userB.deserializeUser());
//Route A
app.post('/routeA', passport.authenticate(`localA`), (req, res) => {
res.redirect(`/routeAA`);
});
app.get('/routeAA', function (req, res) {
res.render('routeA.ejs');
});
//Route B
app.post('/routeB', passport.authenticate(`localB`), (req, res) => {
res.redirect(`/routeBB`);
});
app.get('/routeBB', function (req, res) {
res.render('routeB.ejs');
});
It appears that this is not a new issue. Here are some related posts:
https://github.com/jaredhanson/passport/issues/803
Passport.js multiple local strategies and req.user
In post 803 user @nathan6am, states ....
I ran into the same problem, it's a bit of a hacky solution but I got around it by using req.session?.passport?.user and deserializing the user manually instead of using req.user in the callback.
I'm still struggling to understand how to manually de-serialize so as to force req.user to re-acquire correct values, but I did confirm that the contents of "req.session.passport.user" (for my schema) is the user's email address, so I saved that in a session variable, "req.session.email". My plan was then to write some middleware (in the next route) that would search my DB, using the contents of req.session.email, then use that DB record to extract the data that I would subsequently pass onto my rendered ejs file. It would have looked something like this:
//Route B
app.post('/routeB', passport.authenticate(`localB`), (req, res) => {
req.session.email = req.session.passport.user;
res.redirect(`/routeBB`);
});
app.get('/routeBB', hack, function (req, res) {
res.render('routeB.ejs' {key1: value1, key2: value2 });
});
function hack(req, res, next) {
// find user in DB using req.session.email
// extract need data from DB
// build object comprised of needed data
// key1: value1
// key2: value2
return next();
}
But then I realized that I have other middleware, for other routes, that rely on req.user for authorization (req.user.role=some role) ... so having req.user as undefined isn't something that can work. Is there anyone who can add some color to @nathan6am's post?
Thank you. Tim.