Suppose I need two different passports within one express application (e.g. user & room). So I define two separate vars:
var passport = require('passport');
var roomPassport = require('passport');
then, I initialize them with separate passport strategies:
require('./config/passport')(passport); // pass passport for configuration
require('./config/roompassport')(roomPassport); // pass passport for configuration
the last step is to set them as Express middleware:
// required for passport
application.use(session({ secret: 'ilovepassport;-)' })); // session secret
application.use(passport.initialize({ userProperty: "user" }));
application.use(passport.session()); // persistent login sessions
application.use(roomPassport.initialize({ userProperty: "room" }));
application.use(roomPassport.session()); // persistent login sessions
application.use(flash()); // use connect-flash for flash messages stored in session`
however, if I did it like this, in fact roomPassport overrides passport and instead of having two objects - req.user and req.room, I have got just one req.room but initialized with user data.
It is important to mention that each passports (user or room) could authenticate independently from each other, i.e. there is a scenario where both objects req.user
and req.room
have to exist.
How to resolve this?
EDIT 1
Well, after few more hours, it seems that although I have to separate passport objects, after the call of application.use(roomPassport.initialize({ userProperty: "room" }));
, things get messy - and this is because req.login()
method works with the last attached passport. So instead of calling the correct passport.serializeUser
method, it calls roomPassport.serializeUser
method.
My next question - how to make req.login()
to call the right method?
Strategies are responsible for authenticating requests, which they accomplish by implementing an authentication mechanism. Authentication mechanisms define how to encode a credential, such as a password or an assertion from an identity provider (IdP), in a request.
Passport uses serializeUser function to persist user data (after successful authentication) into session. The function deserializeUser is used to retrieve user data from session and perform some condition-based operations. Now all the endpoints hitting the backend server will go through passport.
Passport's middleware is built in a way that allows you to use multiple strategies in one passport.
The problem your having is that the passport module exports an instantiated Passport object when you require it. And because that object is cached by node when you require it, you get the exact same object every time.
Luckily, the passport module also gives you a reference to the class, meaning you can do this.
var Passport = require('passport').Passport,
passport = new Passport(),
roomPassport = new Passport();
Now you should have two completely separate passport objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With