graphql-starter-kit
graphql-starter-kit copied to clipboard
Add the flexibility of multiple roles
I have code that creates roles, and users can have multiple roles. It also checks if they have the administrator role, rather than using a flag on the user row. If this is useful to add to the template, let me know and I can add it through a PR.
@njhargis sounds good! You're very wellcome to fork the repo, create a branch for the roles implementation, and a PR.
If the roles implementation will end-up simple enough, yet generic and flexible, we may decide to merge it into the main branch, alternatively we can leave it as an example branch.
A few things to note:
- Some developers prefer enforcing permissions using Postgres's row level security policies, while others prefer having security checks at the application level alongside the rest of the (TypeScript) code.
- It can be convinient to have short keys for the roles, e.g.
admin
(short key) +Administrator
(full name) - Some developers would prefer including roles into the authentication (JWT) token, while others would rather not
- How easy it would be to migrate the app to use the new roles if there are any changes; e.g. it might be a good idea to have the list of roles in the code, so that when you deploy a new version, the list of roles would be automatically updated with the rest of the app (as opposed to allow users tweaking the list of roles in the database).
- How the authentication code would look like?
For example, if the list of roles will be included into the authentication (JWT) token, it may look like this:
{
"iss": "https://examle.com",
"aud": "https://example.com",
"sub": "123456",
"exp": 1499863217,
"roles": ["owner"]
}
If authentication is implemented at the application level, it may look something like this:
async resolve(self, args, ctx) {
if (!ctx.user) {
throw new Unuthorized();
}
if (!ctx.user?.roles.some(role => "editor")) {
throw new Forbidden();
}
...
}
The list of roles may look something like this:
export const userRoles = [
{ role: "owner", name: "Owner" },
{ role: "editor", name: "Editor" },
{ role: "collaborator", name: "External Collaborator" }
];
- Roles, may contain the list of permission sets.
- For more complex apps, it should also be possible to group roles.
Further reading
- https://firebase.google.com/docs/firestore/solutions/role-based-access