I'm trying to figure out a good way to set up authentication and authorization on my GRANDstack setup.
I do not want to tie my roles/scope logic to firebase. What if I want to query all staff members from the client? It looks like I'd have to query firebase to get this info, but I only want to authenticate with it, and do everything else with neo4j.
Can you please critic my approach?
Authenticate users through firebase, get firebase id token
with apollo client's useMutation, do a MergeUser mutation with the firebase id token (assuming custom header)
From Apollo server, verify firebase id token, get the user id, and query the neo4j DB
after neo4j's result, sign a custom JWT with the user id, roles and scopes. Return user data + JWT to client
Client updates cache with user data and JWT in localstorage
apollo link detects localstorage token and sets headers.authorization
In addition, coming from Django, I like having permissions (scopes) attached to groups (roles).
So instead of using a enum Roles, I'll make it a type.
Once I get my request authorization token, future queries will be a breeze with graphql-auth-directives.
The only difficulty is getting this MergeUser mutation working properly. Maybe I only need a @doAuthenticate custom
directive, maybe I need a custom resolver. Will start working on that.
If all you're trying to do is authorize the user via firebase or any other auth provider like Auth0. then you could probably keep the user permissions on the user object it's self and then include those in the your context with Apollo requests. That what you've got full control over your user roles/permissions, etc. At least that's my thought.
This is what I was describing. Except that we only query the user scope/roles once on authentication, then get these from the JWT instead of re-querying the user data for every single request.
Thanks for confirming that I'm going in the right direction!
How did you make out with this? I am trying to do the same with GrandStack - use Firebase for authorization/authentication and then query Neo4j with custom roles/scopes. Running into a roadblock with figuring out Firebase and custom JWT's on the user that include the roles/scopes.
@ilyafish once I verify the user's firebase id, I save that as my neo4j user id.
I then use the jsonwebtoken library to sign a new jwt including my user's roles, and set it in the user's request header.
On each request, I decode the jwt with the server's private key, and can trust that the jwt scopes are indeed the user's ones.
In addition, I added a resolver to recreate a jwt if the user's db role has change.
Note that I still need to implement graphql-shield to enforce authorization checks on mutation requests, because directives are only applied to the response.
Hope that helps, cheers.
The role is stored in the db, and I have a local map to get the list of scopes per role.