I'm building a 2 parts login system. Where the a user will login to a main account Account
model, this account will hold access to many teams Team
model, and an account can have 1 user per team User
model. The problem is that I can define an Account
login strategy with passport but I will only be able to serialize and deserialize using Account
model, but when I want to redirect or login the Account
with their User
specific data related to a Team
I can't log them using passport. I need some ideas or solutions, maybe there's some passport strategy out there I could use.
PS: think of this like a slack login system kind of works, main account (email) can hold multiple teams or chat groups with speific details on each.
If I understood your need correctly I believe you have two options - register multiple (de)serializers, or put more logic into your (de)serialization implementations.
While not really documented, you can register multiple serialize and deserialize functions. If the first function is not successful it should call done('pass');
to have the execution continue to the next (de)serializer, eg. (note that the code examples are just off the top of my head):
passport.deserializeUser((obj, done) => {
Account.deserialize(obj)
.then((account) => done(null, account))
.catch((err) => done('pass'));
});
passport.deserializeUser((obj, done) => {
User.deserialize(obj).then((user) => done(null, user))
});
You are not limited to using the apparently builtin (de)serialization of the ORM/ODM of your choice. Thus you can do any custom logic you need in the serialization functions. For example, put the model instance ID and type into an object in serialization, and use them when deserializing.
passport.serializeUser((obj, done) => {
if (obj instanceof Account) {
done(null, { id: obj.id, type: 'Account' });
} else {
done(null, { id: obj.id, type: 'User' });
}
});
passport.deserializeUser((obj, done) => {
if (obj.type === 'Account') {
Account.get(obj.id).then((account) => done(null, account));
} else {
User.get(obj.id).then((user) => done(null, user));
}
});