Six months ago my team and I started working on my startup Pokerface.io which is a social platform for poker players.
After developing the basic platform using Nodejs, React, Graphql and Apollo, we started thinking about business features and quickly realized that we need to enable the ability to have groups in the platform.
The whole is greater than the sum of its parts — Aristotle
A group is an entity, consisting of a bunch of users, through which users have different capabilities than those that they possess for themselves:
- Acting on behalf of the group* (posting\ liking\ starting a timer as a group)
- Authorization — some actions that a user can’t do, but a group can
- A user should clearly understand if he is now in a “group mode” or not
*We should also consider that in some cases, there are computers dedicated to using the platform, which do not belong to a single user
so I went searching for how do the pros do it? and a few popular philosophies were:
The Naive way
Just create a dummy user with special (greater) permissions and give each user within the group, the dummy user’s credentials (email and password).
This is a failed solution because you can’t really control who has the authentication details and information tends to leak.
Plus, when someone leaves the group they still has the authentication details and you leave your group vulnerable. Yes, you can change the password every time a person leaves, but then you need to rely on people to keep changing the password every time a person leaves the group, which makes it still very vulnerable.
The Facebook way (aka Facebook Pages)
Facebook solves this issue by creating pages — A page can have multiple admins and those admin users have the enhanced permissions, you can easily remove a user from the role of admin and add another.
You can easily act on behalf of a page by changing a combo box and then doing whatever you want.
The main problem in this scenario is that it’s easy to get confused on who is making the action. There were multiple times that I’ve “liked” a certain post, but came to realize that I’ve done this as Pokerface.io (And then had to “unlike” it, select my own personal account and “like” it again…). And with posts you have to copy or re-write the entire post...
The GitHub way (GitHub Organizations)
GitHub has a different philosophy - if a group is a collection of users, then there should not be an action of a group, just a user that is seen as the group doing the action.
A bit confusing but let me simplify this -
If Ash Ketchum wants to post as Team Rocket, Ash Ketchum’s post shouldn't be logged in the DB that Team Rocket posted this but instead it should be logged that Ash Ketchum posted as Team Rocket, and the UI should take care of it looking like it’s a Team Rocket post.
Then the only thing left to take care of is that a user can only do actions on behalf of groups that he belongs to.
A great way of thinking but it doesn’t really comply with our use-case since we should allow dedicated computers (which can’t be exclusive to a single user) to act on behalf of a group, therefore we should allow group actions without the user behind it.
So, after a lot of thought we came up with the alternative,
The ultimate solution (aka The Pokerface.io way)
Eventually, we decided to allow a single user to login as a group but not to allow a group to login — weird right?
When a user (that has membership in any group) logs in to the app, he sees this modal:
You can select one of the groups to login as, or to login as the regular user, all with the same authentication details! But that’s not enough, what if a user uses the platform as himself and then wants to act as a group? Should the user logout and re-login?
So we added a quick switch user button which opens up the same modal and lets you change the user without providing a password (because after all, the user is already logged in and we “know” the groups he belongs to)
But what about the other way around?
When you login or switch to a group and want to go back to being logged-in as the user, then you do need a password (or any user can login as any user within his groups), in order to add this functionality, we’ve decided to use LocalStorage!
Any user that logs-in to Pokerface.io on a computer is being added to the LocalStorage of that computer, then when in group mode and the switch user button is clicked, a modal pops-up with all the users that have previously logged-in on that computer; at that point, the user can either click on any of them and then provide just the password for ease of use, or just write the entire username and password.
Tech and implementation details
And we also have an endpoint whose purpose is “exchanging tokens”. So basically, you provide a token and a group id, and get in return a new token, to authenticate your next requests with.
(Other libraries used for this are: express, passport and apollo-link)
This way we get all our needs fulfilled, and can’t get confused by the question of who is performing the action.
What do you think?