← back

GraphQL Authorization

Written by Matthias Osswald - May 2021
 
 
GraphQL is a flexible solution for interfaces when working with open data. It comes with some disadvantages though when it comes to authorization. The reasons for that are that the query can be quite diverse and comes as an undifferentiated bytestring containing lots of information.

Recently I’ve started to work on a library for authorization using fastapi (checkout the authorization library here). The Goal is to provide a middleware which authorizes request on the basis of an Open Policy Agent client.

Confronted with GraphQL queries I’ve started to figure out how to retrieve enough information out of a query without any deeper knowledge of the types, nodes or relays in place. I ended up with this class which can extract the operations name, type, variables but most importantly will recursively collect the queried selection. The GraphQL analysis can not only provide the selection data but also is easily extendable with nesting limitations (known attack vector (cf. GraphQL Cheat Sheet))

Deciding whether to allow/disallow queries before hitting the actual endpoint makes fine-grained authorization possible, solves security relevant issues and encourages returning/failing fast.

Let’s look at an example how the data extraction by the GraphQL analysis looks like (or can look like). One part of the story is this simple query fetching enrolled students attending the physics course. The response data is supposed to return the students name, subject, and a boolean values whether the student is enrolled (should obviously be true).

"operationName": "getStudents",
"variables": {"subject": "Physics", "enrolled": True},
"query": """query getStudents(
$subject: String,
$enrolled: Boolean){
  students(
  subject: $subject,
  enrolled: $enrolled){
    Student {
      name
      subject
      enrolled
    }
  }
}
"""

By putting the GraphQL analysis in place all the below data can be extracted from the query. In terms of authorization this data can now be sent to the Open Policy Agent to be assessed with respect to the Rego policies.

"gql_info": [
    {
        "name": "getStudents",
        "operation": "query",
        "selection_set": [
            ["students", ["Student", ["name", "subject", "enrolled"]]]
        ],
        "variables": {"enrolled": "Boolean", "subject": "String"},
    }
],