How to handle Authorization in GraphQL servers?
Shall I pass the JWT token in the Authentication header of every requests and check for the authorized user after resolve()
and check for the role of user on every query
and mutation
Introduction
First of all, a common approach for authentication as you state is using a signed JWT that contains the id of the user making the request.
Now let's have a look at the different parameters we can use when considering the authorization of a given request.
who is making the request?
determined by the user id mentioned above. More information about the requester like associated user roles can be looked up in the database. This means that we need to maintain a
User
table if we are using SQL for example, and add new users to this table on registration.which operation should be executed?
users might be granted read-only access. Certain mutations or queries are only allowed for certain users.
which fields are included in the query/mutation response?
some fields should be only accessed by certain users.
Permissions
With this information in mind, we can come up with different permission systems. Most commonly, in such a system, no operation is allowed by default. When a request comes in, the parameters mentioned above can be matched with the existing permissions and if a matching permission is found, the request is granted.
Role-based permissions
In certain applications, a role-based approach works great.
For example, for a simpler version of Stack Overflow, we could have the roles EVERYONE
, AUTHENTICATED
and MODERATOR
. A sensible permission rule could be this:
EVERYONE
can read questions/answers- requester: doesn't matter (everyone)
- operations:
allQuestions
,allAnswers
queries - fields:
text
Other rules (leaving parameters out):
* AUTHENTICATED
users can create new questions/answers
* MODERATOR
users can create new questions/answers
* MODERATOR
users can delete questions/answers.
Now for example, if a non-authenticated requests comes in that asks for the allQuestions
query, that's fine as we find a permission that allows it (the first).
If on the other hand an authenticated requests comes in for a user that doesn't have the MODERATOR
role and includes the deleteQuestion
mutation, there is no permission to be found for these parameters. So the request is rejected.
Graph permissions
While role-based permissions represent a solid permission system already, they are not suited at all if we want to make granting permission dependant on things like the relation between the requester and the requested node. In our example, it would be quite the work to add the simple rule that any user is allowed to delete their own questions/answers.
At Graphcool, we have come up with a powerful yet rather simple approach that we call graph permissions to tackle this issue. Let's make the following additional parameters available when checking permissions:
which node is about to be accessed or modified?
determined by a node id
Then we can express permissions using a GraphQL query against a special permission schema to grant or reject permissions on a node level. Access to a given node is only given, if the permission query contains at least one leaf-node that is not null
.
In our case, we could specify this permission query:
query {
allAnswers(filter:{
authorId: $userId,
id: $nodeId
}) {
id
}
}
For a given node and user specified by GraphQL variables $userId
and $nodeId
, we use a query argument filter
to either return an empty list if the node wasn't created by the current user, or something non-null otherwise.
来源:https://stackoverflow.com/questions/41206123/authorization-in-graphql-servers