Setting up an API rule to execute queries and mutations regardless of @auth rules on Dgraph with Auth0
Dgraph is recently getting more and more attention and seems to find it’s spot as the the only truly GraphQL-native database. Although Dgraph is a poerful tool, it lacks options in some specific use-cases.
Introduction
We are using Dgraph Cloud in the Shared Cluster version for our production ready application. We have alos chosen Auth0 as our authentication service to work with Dgraph (here’s a Blogpost how to get Dgraph to work with Auth0). Since our app also allows users to upload files to an AWS S3 bucket, we obviously ran into the use-case to implement lambdas and thus rely on API calls to fetch or update data on Dgraph.
However, I don’t want to get into detail how to secure queries and mutations on Dgraph but in principle there are two ways of doing so. Let’s start with a quick example to clarify the problem.
The setup
Imagine a type definition in your schema:
If we do not add auth rules AND do not allow public access, eg.via the Graph Cloud Console Access Tab, we can perform queries and mutations by simply using our Admin API or Client API Key, which can be generated in the Dgraph Cloud web-interface.
In this case queries and mutations for this node are not publicly available via your Dgraph endpoint. You can only perform such tasks by submitting either your client or your admin key in the request header.
CASE 1: read/write access for “Quote” is NOT public
Perfect, your eg. lamda only needs the API key and you can securely manipulate data for this node 👌. A possible implementation, using graphql-requestcould look like this
Note the DG-Auth header which will allow our imaginary lambda to perform mutations as well as queries on our Dgraph server.
So far so good but in my experience there are a lot of use-cases where you want to make read/write access public and still want your lambda to be able to perform the tasks above. Unfortunately, as soon as we give public access to read/write of Quote, the lambda will not be able to perform tasks via the API key anymore — we need a valid token!
The JWT and user claim for Auth0
I have mentioned earlier that we use Auth0 for authentication in our project. I guess it will be similar with other authentication services but for the sake of this article, we will stick with Auth0. Not going into detail here, I assume that you have protected your Dgraph endpoint according to the documentation. If you have done so, you probably have a login flow which issues your user a token. Without going too much into detail about generating custom claims for your users with Auth0, let’s assume we already have a role based authentication in place, which we can use for our @auth rules. Let’s further assume we have 2 user roles which will appear within our claim as role: <user_role> and user roles can be:
ADMINUSER
where the USER is only allowed to read all the quotes and the ADMIN can read AND publish new posts. In order to achieve this we have to extend our Quote type:
Now
- only logged in users (we need the token claim) and users with either role
ADMINorUSERcan query quotes - only users with role
ADMINcan publish new quotes
You probably know all this but stay with me — what if we want to get our lambda involved now? The lambda is not a user and thus has no token. The answer is setting up a machine to machine login flow in Auth0.
CASE 2: Allow Machine to Machine login flow when read/write for Quote is public
Let’s get your lambda a token! Log into you Auth0 dashboard and manoeuvre to Actions > Flows. Then click on Machine to Machine and add an appropriate M2M flow. I named mine M2M Claim but you can name it whatever you want.
You will see the web IDE with an empty handler. You can now simply add whatever you want to the M2M claim but I suggest some sort of UUID which is a bit harder to guess:
I have added a single parameter isApiCall but you could also have role: "LAMBDA" for example (or even a combination of secret key and role is possible). Whatever suits your needs best. Then we just need to add this to our @auth rules
Finally, we only need to extend our lamda which needs to get our M2M token from Auth0 first:
Now your lambda AND your users can query and mutate even if Quote read/write is public! 🙌
I hope this helps! It took me a while to figure out how to do this. It’s my first Medium article so please let me know if this makes sense to you! Feel free to contact me or simply leave me a comment!
Thanks!
