Configuring permission rules
Introduction
Access control rules in Hasura are defined at a role, table and action (insert, update, select, delete) level granularity:

Requests to Hasura should contain the reserved session variable X-Hasura-Role to indicate the requesting user's role,
and the table and action information is inferred from the request itself. This information is used to determine the
right permission rule to be applied (if one has been defined) to the incoming request.
Hasura converts GraphQL queries (or mutations/subscriptions) into a single SQL query that is executed on the configured database instance. Hasura also includes constraints from permission rules in the SQL query itself.
Permissions are essentially a combination of boolean expressions and column selections that impose constraints on the data being returned or modified.
Let's take a look at the different configuration options available to define a permission rule. Permission rules are defined for each role, table, operation (insert, select, update, delete) by using the Console or the metadata APIs for permissions.
Operation permissions
Select permissions
For select operations or for GraphQL queries, you can configure the following:
- Row-level permissions
 - Column-level permissions
 - Aggregation queries permissions
 - Row fetch limit
 - Disabling root fields
 
Insert permissions
For insert operations or for GraphQL mutations of the type insert, you can configure the following:
Update permissions
For update operations or for GraphQL mutations of the type update, you can configure the following:
Delete permissions
For delete operations or for GraphQL mutations of the type delete, you can configure the following:
Permission categories
Row-level permissions
Row-level permissions are boolean expressions that help you restrict access to rows depending on the operation being
performed. E.g. in the case of select, your boolean expression is run on every row to determine whether that row can
be read. In the case of insert, the boolean expression determines whether or not the mutation is allowed.
Row-level permissions are defined using operators, static values, values in columns (including those in related tables or nested objects) and session variables.
Using column operators to build rules
Type-based operators (depending on the column type) are available for constructing row-level permissions. You can use the same operators that you use to filter query results along with a few others to define permission rules.
See the API reference for a list of all supported column operators.
For example, the following two images illustrate the different operators available for integer and text types:


Using boolean expressions
The following is an example of a simple boolean expression to restrict access for select to rows where the value in
the id column is greater than 10:
- Console
 - CLI
 - API
 
You can define permissions using boolean expressions on the Hasura Console as follows:

You can define permissions using boolean expressions in the metadata > databases > [database-name] > tables >
[table-name].yaml file, eg:
- table:
    schema: public
    name: author
  select_permissions:
    - role: user
      permission:
        columns: []
        filter:
          id:
            _gt: 10
Apply the metadata by running:
hasura metadata apply
You can define permissions using boolean expressions when using the permissions metadata API. Example with a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "author",
      "role": "user",
      "permission": {
         "columns": "*",
         "filter": {
            "id": {"_gt": 10}
         }
      }
   }
}
You can construct more complex boolean expressions using the _and, _or and not operators:

For example, using the _and operator, you can construct a rule to restrict access for select to rows where the
value in the id column is greater than 10 and the value in the name column starts with "a" or "A":
- Console
 - CLI
 - API
 
You can define permissions using the _and operator on the Hasura Console as follows:

You can define permissions using the _and operator in the metadata > databases > [database-name] > tables >
[table-name].yaml file eg:
- table:
    schema: public
    name: author
  select_permissions:
    - role: user
      permission:
        columns: []
        filter:
          _and:
            - id: { _gt: 10 }
            - name: { _ilike: a% }
Apply the metadata by running:
hasura metadata apply
You can define permissions using the _and operator when using the
permissions metadata API. Example with a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "author",
      "role": "user",
      "permission": {
         "columns": "*",
         "filter": {
            "$and": [
               {
                  "id": {
                     "_gt": 10
                  }
               },
               {
                  "name": {
                     "_ilike": "a%"
                  }
               }
            ]
         }
      }
   }
}
Using session variables
Session variables that have been resolved from authentication tokens by either your authentication webhook or by Hasura using the JWT configuration are available for constructing row-level permissions.
For example, to allow an author to access only their articles, you can use the X-Hasura-User-ID session variable
to construct a rule to restrict access for select to rows in the articles table where the value in the id column
is equal to the value in the session variable (assuming this variable is being used to indicate the author's ID):
- Console
 - CLI
 - API
 
You can define session variables in permissions on the Hasura Console:

You can define session variables in permissions in the metadata > databases > [database-name] > tables >
[table-name].yaml file, eg:
- table:
    schema: public
    name: article
  select_permissions:
    - role: author
      permission:
        columns:
          - title
          - content
        filter:
          id:
            _eq: X-Hasura-User-Id
Apply the metadata by running:
hasura metadata apply
You can define session variables in permissions tables when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "article",
      "role": "author",
      "permission": {
         "columns": "*",
         "filter": {
            "id": "X-Hasura-User-Id"
         }
      }
   }
}
Support for using session variables for array operators like _in, _nin, _has_any_keys, _has_all_keys is
available in versions v1.0.0-beta.3 and above.
When you use array operators such as _in in the permissions builder in the Hasura Console, it will automatically open
an array for your values. If your session variable value is already an array, you can click the [X-Hasura-Allowed-Ids]
suggestion to remove the brackets and set your session variable in its place.
Using relationships or nested objects
You can leverage table relationships to define permission rules with fields from a nested object.
For example, let's say you have an object relationship called agent from the authors table to another table
called agent (an author can have an agent) and we want to allow users with the role agent to access the details of
the authors who they manage in authors table. We can define the following permission rule that uses the aforementioned
object relationship:
- Console
 - CLI
 - API
 
You can use a nested object to build rules on the Hasura Console:

You add permissions using relationships or nested objects in the metadata > databases > [database-name] > tables >
[table-name].yaml eg:
- table:
    schema: public
    name: author
  select_permissions:
    - role: agent
      permission:
        columns: []
        filter:
          agent:
            agent_id:
              _eq: X-Hasura-User-Id
Apply the metadata by running:
hasura metadata apply
You add permissions using relationships or nested objects when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
   {
      "type": "pg_create_select_permission",
      "args": {
         "source": "<db_name>",
         "table": "author",
         "role": "agent",
         "permission": {
            "columns": "*",
            "filter": {
               "agent": {
                  "agent_id": {
                     "_eq": "X-Hasura-User-Id"
                  }
               }
            }
         }
      }
   }
This permission rule reads as "if the author's agent's id is the same as the requesting user's id , allow
access to the author's details."
- The above example would have worked even if the relationship were an array relationship. In our example, the
corresponding rule for an array relationship would have read "if any of this author's agents' 
idis the same as the requesting user'sid, allow access to the author's details". - You can also check out this more elaborate example.
 
Using unrelated tables / views
You can use the _exists operator to set a permission rule based on tables/views that are not related to our table.
For example, say we want to allow a user to insert an article only if the value of the allow_article_create
column in the users table is set to true. Let's assume the user's id is passed in the X-Hasura-User-ID session
variable.
- Console
 - CLI
 - API
 
You can set permissions using unrelated tables on the Hasura Console as follows:

You can set permissions using unrelated tables in the metadata > databases > [database-name] > tables >
[table-name].yaml, eg:
- table:
    schema: public
    name: article
  insert_permissions:
    - role: user
      permission:
        check:
          _exists:
            _where:
              _and:
                - id: { _eq: X-Hasura-User-Id }
                - allow_article_create: { _eq: true }
            _table:
              schema: public
              name: users
        columns:
          - content
          - id
          - title
Apply the metadata by running:
hasura metadata apply
You can set permissions for unrelated tables when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_insert_permission",
   "args": {
      "source": "<db_name>",
      "table": "article",
      "role": "user",
      "permission": {
         "columns": "*",
         "check": {
            "$exists": {
               "_table": "users",
               "_where": {
                  "$and": [
                     {
                        "id": "X-Hasura-User-Id"
                     },
                     {
                        "allow_article_create": true
                     }
                  ]
               }
            }
         }
      }
   }
}
This permission rule reads as "if there exists a row in the table users whose id is the same as the requesting
user's id and has the allow_article_create column set to true, allow access to insert articles."
Column-level permissions
Column-level permissions determine access to columns in the rows that are accessible based on row-level permissions.
- Console
 - CLI
 - API
 
Column-level permissions are simple selections on the Hasura Console:

You can set column-level permissions in the metadata > databases > [database-name] > tables >
[table-name].yaml file, eg:
- table:
    schema: public
    name: article
  select_permissions:
    - role: author
      permission:
        columns:
          - author_id
          - id
          - content
          - title
        filter:
          author_id:
            _eq: X-Hasura-User-Id
Apply the metadata by running:
hasura metadata apply
You can set column-level permissions when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "article",
      "role": "author",
      "permission": {
         "columns": [
            "id",
            "title",
            "content",
            "author_id"
         ],
         "filter": {
            "author_id": "X-Hasura-User-Id"
         }
      }
   }
}
In this example, the role author has only partial access to columns of the accessible rows for the select operation.
Row fetch limit
In the case of select operations, the number of rows to be returned in the response can be limited using this
configuration:
- Console
 - CLI
 - API
 
You can set a row fetch limit on the Hasura Console as follows:

You can set a row fetch limit for a table in the metadata > databases > [database-name] > tables >
[table-name].yaml file, eg:
- table:
    schema: public
    name: author
  select_permissions:
    - role: user
      permission:
        columns:
          - id
          - name
        filter:
          user_id:
            _gt: 10
        limit: 20
Apply the metadata by running:
hasura metadata apply
You can a row fetch limit for a table when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "author",
      "role": "user",
      "permission": {
         "columns": "*",
         "filter": {
            "id": {
               "_gt": 10
            }
         },
         "limit": 20
      }
   }
}
In the above example, this configuration restricts the number of accessible rows (based on the rule:
{"id":{"_eq":"X-Hasura-User-Id"}}) to 20.
Aggregation queries permissions
In the case of select operations, access to aggregation queries can be
enabled for a given role using this configuration.
- Console
 - CLI
 - API
 
You can enable aggregation queries permissions on the Hasura Console as follows:

You can allow aggregation query permissions in the metadata > databases > [database-name] > tables >
[table-name].yaml file, eg:
- table:
    schema: public
    name: author
  select_permissions:
    - role: user
      permission:
        columns:
          - id
          - name
        filter:
          user_id:
            _gt: 10
        allow_aggregations: true
Apply the metadata by running:
hasura metadata apply
You can allow aggregation query permissions when using the permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
   "type": "pg_create_select_permission",
   "args": {
      "source": "<db_name>",
      "table": "author",
      "role": "user",
      "permission": {
         "columns": [
            "id",
            "name"
         ],
         "filter": {
            "id": "X-Hasura-User-Id"
         },
         "allow_aggregations": true
      }
   }
}
In the above example, the role user is allowed to make aggregation queries.
Column presets
While this is strictly not a permission configuration, defining
role-based column presets on any column automatically removes
access to it. This preset can be defined for insert and update operations. This configuration is also very useful to
avoid sending sensitive user-information in the request and leverage session variables or static data instead.
- Console
 - CLI
 - API
 
You can define column presets for either insert or update operations in the Hasura Console as follows:

You can define column presets for table columns in the metadata > databases > [database-name] >
tables > [table-name].yaml, eg: public_users.yaml:
table:
  name: users
  schema: public
insert_permissions:
  - role: user
    permission:
      check: {}
      set:
        id: x-hasura-User-Id
      columns:
        - id
Apply the metadata by running:
hasura metadata apply
You can define column presets with either the insert or update permissions metadata API. Example using a Postgres db:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
  "type": "pg_create_insert_permission",
  "args": {
    "table": {
      "name": "users",
      "schema": "public"
    },
    "role": "user",
    "permission": {
      "check": {},
      "columns": [
        "id"
      ],
      "set": {
        "id": "x-hasura-user-id"
    }
  },
    "source": "default"
  }
}
Backend only
If a permission is marked as backend_only, the mutation is accessible to the given role only if
x-hasura-use-backend-only-permissions session variable exists and is set to true and request is made with
x-hasura-admin-secret set if any auth is configured.
This might be useful if you would like to hide a mutation from the public facing API but allow access to it via a "trusted backend".
Setting backend-only is currently available for insert, update and delete mutations.
- Console
 - CLI
 - API
 
You can set a mutate permission for a role as backend only in the Hasura Console as follows:

You can set a mutate permission for a role as backend only in the metadata >
databases > [database-name] > tables > [table-name].yaml file, eg: public_users.yaml:
table:
  name: users
  schema: public
insert_permissions:
  - role: user
    permission:
      check: {}
      columns:
      - id
      backend_only: true
delete_permissions:
  - role: user
    permission:
      backend_only: true
      filter: {}
You can set a mutate permission for a role as backend only with the Metadata API and the insert, update or delete permissions.
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
  "type": "pg_create_insert_permission",
  "args": {
    "table": {
      "name": "users",
      "schema": "public"
    },
    "role": "user",
    "permission": {
      "check": {},
      "columns": [
        "id"
      ],
      "set": {},
      "backend_only": true
    },
    "source": "default"
  }
}
Back-end only permissions for update and delete mutations are supported in Hasura GraphQL engine versions v2.8.0
and above.
Disabling Root Fields
When you track a table in Hasura, by default it exposes all the root fields available to the role. However, sometimes you may want a role to only have access to certain root fields of a table or have the table be accessible only through relationships.
Only query and subscription root fields can be disabled.
Disabling root fields is supported in version v2.8.0 and above.
- Console
 - CLI
 - API
 
You can disable specific root fields for query and subscription by unchecking them in the Select permission for the table and role in Console as follows:

You can disable root fields for queries and subscriptions specifying which are available for the
select_permissions by updating the specific metadata > databases > [database-name] > tables > [table-name].yaml file
eg:
table:
  name: users
  schema: public
select_permissions:
  - role: user
    permission:
      columns:
        - id
      filter: {}
      query_root_fields:
        - select_by_pk
      subscription_root_fields:
        - select
        - select_by_pk
        - select_aggregate
delete_permissions:
  - role: user
  permission:
    backend_only: true
    filter: {}
Setting the value of query_root_fields or subscription_root_fields to null or not defining it at
all implies that all fields are allowed and an empty array means no fields are allowed.
You can disable root fields for Select permissions with the
permissions metadata API by specifying which should be available in
the  query_root_fields and subscription_root_fields arrays, eg:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
  "type" : "pg_create_select_permission",
  "args" : {
    "table" : "users",
    "role" : "user",
    "source": "default",
    "permission" : {
      "columns" : "*",
      "filter" : {
        "is_public": true
      },
      "query_root_fields": ["select_by_pk"],
      "subscription_root_fields": ["select", "select_by_pk"]
    }
  }
}
Setting the value of query_root_fields or subscription_root_fields to null or not defining it at
all implies that all fields are allowed and an empty array means no fields are allowed.
Use cases
1. Allow a table to be accessible only through a relationship
Let's say we have two tables, authors and articles defined as follows:
| Table | Columns | Hasura relationships | 
|---|---|---|
| author | id, first_name, last_name, created_at, is_active | articles (array) | 
| articles | id, author_id, title, content, created_at, is_public | author (object) | 
We would like to configure permissions of the guest role such that they are only able to access the articles of the
authors which they can access i.e. access the articles table only through the authors -> articles relationship.
Modifying the select permission of the articles table:

Note that query_root_fields and subscription_root_fields are set to [], which means that the guest role
won't be able to access the articles table directly, but will be able to access it through the articles
relationship.
If root fields are disabled then you may try to simplify the row filter permissions by giving it "all rows" but you
should be cautious here because the field may be accessible through a different type e.g. returning field in a
mutation output type.
2. Access only via primary key
Let's say you want to allow a client to fetch data from a table only if the client knows the primary key of a row in that table.
In this case, regardless of the permission on the table, only <table>_by_pk should be exposed in query_root.
This can be done in the following way:

3. Disable subscription fields
You can allow a role to only be able to make query and not subscription requests.
This can be done in the following way:

Enterprise Grade Authorization - Watch Webinar.

