Disclaimer: These are just my personal notes to help me articulate concepts I’m learning. They’re not meant to be used as a tutorial.
Today I’m going to walk through how I built a v1 of a role-based permission system in my GraphQL server. This is a bare-bones implementation to demonstrate the concepts, with improvements to come later.
Imagine we want our app to be subscription-based. We will have 2 types of users: “Basic” users and “Premium” users. Premium users will be able to access premium content.
How do we build this in GraphQL?
There are 4 main things that need to happen:
Auth Token/Cookie: Include a
roleproperty on the
premiumMutation- check that
context.me.role === ‘PREMIUM’before returning premium content
updateRole(newRole: String!): User!
Let’s go one by one:
Update the User model to include a role:
2. Auth Token/Cookie: Include a role property on the user
We have a function called
getMe in our
index.js file that runs on every request. It does the following:
Takes the request as the only argument
Looks at req.cookies.token
If the token is verified, it returns the user object inside the token
We use this user to populate the
meproperty on our
contextthat becomes available in our resolvers
We can then do authentication on a resolver-level by simply checking that
I won’t go too much into detail about this mechanism, as this post is just about roles, not token/cookie-based auth. The only important thing to note is that the getMe function needs to be able to access
user.role in the token.
To do this, we can update our
createToken function that gets used in our
signup resolvers, to include the
So we pass this function a full user object (returned from the database) and it strips out all the sensitive info and just puts some safe and useful properties into the token.
As a result, the token in our auth cookie now contains the role property, which we can verify in jwt.io like this:
Ok so now the role is in our database, in our auth cookie, and in our resolvers (via
context.me) now we can check the user role in our resolvers to make decisions about what content to show.
3. Mutation: premiumMutation
Let’s show an example of checking the user role in a mutation:
First, it checks if you’re logged in.
Then, it checks if you’re a Premium member.
Then, if those two checks have passed, it returns your premium content.
4. Mutation: updateRole
To test this system, we need a way to update the role on the user.
We can create a new User mutation that takes the
newRole as the only argument, and returns a
User. (We don’t need a
userId argument because we’re getting that from
context.me in our resolvers).
We’re doing a few key things:
Make sure they’re logged in to update the role
Update the user’s role in the database
Reset the cookie/jwt to reflect the new role
Return the updated user
Those are the basics of setting up a role-based permission system in a GraphQL server. There are some key improvements that I hope to make tomorrow:
We don’t want the client to pass any old string for the role. It should strictly be set to either
2 ways to do this:
With enums in GraphQL
Sequelize validation rules on the model
Return the role to the client from the GraphQL API (not just with the auth token) by resolving the
rolefield on the