We’re overhauling Dgraph’s docs to make them clearer and more approachable. If you notice any issues during this transition or have suggestions, please let us know.

Dgraph support Attribute Based Access Control (ABAC) on GraphQL API operations: you can specify which data a user can query, add, update or delete for each type of your GraphQL schema based on JWT claims, using the @auth directive and graph traversal queries.

To implement graph traversal rule on GraphQL API operations :

  1. Ensure your have configured the GraphQL schema to Handle JWT tokens using # Dgraph.Authorization This step is important to be able to use the JWT claims
  2. Annotate the Types in the GraphQL schema with the @auth directive and specify conditions to be met for query, add, update or delete operations.

A graph traversal rule is expressed as GraphQL query on the type on which the @auth directive applies.

For example, a rule on Contact type can only use a queryContact query :

type Contact @auth(
  query: { rule: "query { queryContact(filter: { isPublic: true }) { id } }" },
  add: ...
  update: ...
  delete: ...
) {
  <type definition>
  ...
}

You can use triple quotation marks. In that case the query can be defined on multiple lines.

The following schema is also valid:

type Contact @auth(
  query: { rule: """query {
    queryContact(filter: { isPublic: true }) {
        id
    }
    } """
}) {
  <type definition>
  ...
}

The rules are expressed as GraphQL queries, so they can also have a name and parameters:

type Todo
  @auth(
    query: {
      rule: """
      query ($USER: String!) {
          queryTodo(filter: { owner: { eq: $USER } } ) {
              id
          }
      }
      """
    }
  ) {
  id: ID!
  text: String! @search(by: [term])
  owner: String! @search(by: [hash])
}

The parameters are replaced at runtime by the corresponding claims found in the JWT token. In this case, the query is executed with the value of the USER claim.

When a user sends a request on /graphql endpoint for a get<Type> or query<Type> operation, Dgraph executes the query specified in the @auth directive of the Type to build a list of “authorized” UIDs. Dgraph returns only the data matching both the requested data and the “authorized” list. That means that the client can apply any filter condition, the result is the intersection of the data matching the filter and the “authorized” data.

The same logic applies for update<Type> and delete<Type>: only the data matching the @auth query are affected.

type Todo
  @auth(
    delete: {
      or: [
        {
          rule: """
          query ($USER: String!) {
            queryTodo(filter: { owner: { eq: $USER } } ) {
                __typename
            }
          }
          """
        } # you are the author graph query
        { rule: "{$ROLE: { eq: \"ADMIN\" } }" }
      ]
    }
  )

In the context of @auth directive, Dgraph executes the @auth query differently that a normal query : if the query has nested blocks, all levels must match existing data. Dgraph internally applies a @cascade directive, making the directive more like a pattern matching condition.

For example, in the cases of To do, the access depends not on a value in the to do, but on checking which owner it’s linked to. This means our auth rule must make a step further into the graph to check who the owner is :

type User {
  username: String! @id
  todos: [Todo]
}

type Todo
  @auth(
    query: {
      rule: """
      query ($USER: String!) {
          queryTodo {
              owner(filter: { username: { eq: $USER } } ) {
                  __typename
              }
          }
      }
      """
    }
  ) {
  id: ID!
  text: String!
  owner: User
}

The @auth query rule only returns to dos having an owner matching the condition: the owner username must be equal to the JWT claim USER.

All blocks must return some data for the query to succeed. You may want to use the field __typename in the most inner block to ensure a data match at this level.

Rules combination

Rules can be combined with the logical connectives and, or and not. A permission can be a mixture of graph traversals and role based rules.

@auth on interfaces

The rules provided inside the @auth directive on an interface are applied as an AND rule to those on the implementing types.

A type inherits the @auth rules of all the implemented interfaces. The final authorization rule is an AND of the type’s @auth rule and of all the implemented interfaces.

Claims

Rules may use claims from the namespace specified by the Dgraph.Authorization or claims present at the root level of the JWT payload.

Error handling

When deploying the schema, Dgraph tests if you are using valid queries in your @auth directive.

For example, using queryFilm for a rule on a type Actor results in an error:

resolving updateGQLSchema failed because Type Actor: @auth: expected only queryActor rules,but found queryFilm