Ask a Question

RBAC rules

Dgraph support Role Based Access Control (RBAC) on GraphQL API operations: you can specify who can invoke query, add, update and delete operations on each type of your GraphQL schema based on JWT claims, using the @auth directive.

To implement Role Based Access Control 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.
  3. Deploy the GraphQL schema either with a schema update or via the Cloud console’s Schema page.

The generic format of RBAC rule is as follow

type User @auth(
    query: { rule:  "{$<claim>: { eq: \"<value>\" } }" },
    add: { rule:  "{$<claim>: { in: [\"<value1>\",...] } }" },
    update: ...
    delete: ...
)

RBAC rule supports eq or in functions to test the value of a JWT claim from the JWT token payload.

The claim value may be a string or array of strings.

For example the following schema has a @auth directive specifying that a delete operation on a User object can only be done if the connected user has a ‘ROLE’ claim in the JWT token with the value “admin” :

type User @auth( 
     delete: { rule: "{$ROLE: { eq: \"admin\" } }"} 
    ) { 
    username: String! 
    @id todos: [Todo] 
}

The following JWT token payload will pass the test (provided that Dgraph.Authorization is configured correctly with the right namespace)

{
  "aud": "dgraph",
  "exp": 1695359621,
  "https://dgraph.io/jwt/claims": {
    "ROLE": "admin",
    "USERID": "[email protected]"
  },
  "iat": 1695359591,
  ...
}

The rule is also working with an array of roles in the JWT token:

{
  "aud": "dgraph",
  "exp": 1695359621,
  "https://dgraph.io/jwt/claims": {
    "ROLE": ["admin","user"]
    "USERID": "[email protected]"
  },
  "iat": 1695359591,
  ...
}

In the case of an array used with the “in” function, the rule is valid is at least one of the claim value is “in” the provided list.

For example, with the following rule, the previous token will be valid because one of the ROLE is in the authorized roles.

type User @auth( 
     delete: { rule: "{$ROLE: { in: [\"admin\",\"superadmin\"] } }"} 
    ) { 
    username: String! 
    @id todos: [Todo] 
}

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.

In the todo app, you can express, for example, that you can delete a Todo if you are the author, or are the site admin.

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

claims

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

For example, given the following JWT payload

{
   "https://xyz.io/jwt/claims": [
      "ROLE": "ADMIN"
   ],
  "email": "[email protected]"
}

If https://xyz.io/jwt/claims is declared as the namespace to use, the authorization rules can use $ROLE but also $email.

In cases where the same claim is present in the namespace and at the root level, the claim value in the namespace takes precedence.

@auth on Interfaces

The rules provided inside the @auth directive on an interface will be 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.