Securing graphql Services without Code (including prisma & neo4j)
Many graphql backend implementations are quite immature when it comes to security. In an ideal world we could simply annotate a schema using graphql sdl to enforce security rules.
To illustrate how a graphql proxy might solve this problem I’ll explain two scenarios and a possible solution.
Scenario 1: Multi tenant SaaS Company using prisma
A multi tenant SaaS Company makes use of prisma as a primary data store. The problem: They don’t want to expose all fields to the public. How could they easily hide some of the fields without writing a graphql server on their own?
Let’s have a look at a very simple example schema:
In the original schema all users can access the field “sensitiveInformation”. To hide the field from the public we can use the graphql-go-tools staticProxy by simply omitting the field from the schema. For more information on the topic see the following link:
This section describes advanced use cases of the validation middleware.jens-neuse.gitbook.io
The proxy graphql schema might look like this:
If a user has only access to the proxy he won’t be able to request the field “sensitiveInformation” as this would result in an invalid request. To enable this functionality the staticProxy makes use of the validation middleware. A detailed explanation on this middleware can be found here:
The Validation Middleware is a Implementation of all rules specified in the graphql specification to validate Requests…jens-neuse.gitbook.io
Scenario 2: Enterprise Company using neo4j graph database
A company uses the Neo4j graph database in the backend. They are using the graphql plugin to expose the database to the frontend. They have sensitive data in the database that should only be accessible for the content creators itself. What they want to achieve is that based on a request header (user id) they want to rewrite requests if the user accesses certain fields.
Let’s see a simple example schema:
As you can see in this very basic schema a user must always provide his id (field “user”) to retrieve documents. Neo4j is a database and doesn’t make assumptions about the usage so it’s up to the user to provide his id. As you can imagine it’s a security issue to let the user provide the argument on his own. It would be good if we could remove the argument from the public schema and set it via a header. This way we can implement our own authorization logic to set the header before invoking the graphql service.
Let’s have a look how the schema might look like if we want to fix this security issue:
First we add the required directive definition “addArgumentFromContext” so that the proxy can handle it. You’ll find more information on the Context Middleware via this link:
You can see that the argument “user” is removed from the documents field. The user is no longer allowed to provide a “user ” argument.
Next you can find that there’s a directive on the documents field. This directive tells the Context Middleware to add the value from the key “user” as argument “user” to the field. The value will be extracted from the request header.
All you have to do is setup an authorization service in front of the proxy and set the header accordingly.
Got interested in using the proxy? I’d be happy to learn how you’d use it to secure your graphql services. If you find an error or have ideas for additional middlewares please open up an issue on github.