Reputation: 4694
So, I have an app that has two types of 'user': humans and devices.
Humans log in using username/password (local strategy). Devices log in using a certificate.
They are very different things, so this isn't the same as having special access for admin users versus normal users. I can't have a single db table for all entities that can log in.
I understand how I can have multiple authentication strategies (I just differentiate by endpoint), but I am a bit stumped on how to handle deserialization of the token for incoming requests. Express/passport seems to allow for only one deserializeUser function I can write.
Furthermore, I'd like to decouple these two types so I can keep devices and humans in their own code rather than have a monolithic deserialize function that sorts them out.
Ideally, I'd be able to have two deserializeUser functions and the right one gets called depending on the token format, but I don't see how best to do that.
Any suggestions?
Upvotes: 1
Views: 2564
Reputation: 4694
I ended up standardizing on a minimal set of common elements each user type must have:
This allows me to include the type in the serialization and only look up the entity in the correct table upon deserialization.
This is pretty close to what I was hoping to get. I'd have preferred to not have to have central serializer/deserializer functions, but I feel this is the minimum compromise I could make.
Here's the code for serializing and deserializing:
passport.serializeUser(function (entity, done) {
done(null, { id: entity.id, type: entity.type });
});
passport.deserializeUser(function (obj, done) {
switch (obj.type) {
case 'user':
User.findById(obj.id)
.then(user => {
if (user) {
done(null, user);
}
else {
done(new Error('user id not found:' + objid, null));
}
});
break;
case 'device':
Device.findById(obj.id)
.then(device => {
if (device) {
done(null, device);
} else {
done(new Error('device id not found:' + obj.id, null));
}
});
break;
default:
done(new Error('no entity type:', obj.type), null);
break;
}
});
Upvotes: 2
Reputation: 314
I understood your requirement that you need a different user type login so you can use request parameter in passport to identify user type so your function will remain common.
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',// this is the virtual field on the model
passReqToCallback: true
},
function (req, email, password, done) {
// get req here
enter code here
});
Upvotes: 0