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:
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
tables.yaml
file inside the metadata
directory:
- 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:
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
tables.yaml
file inside the metadata
directory:
- 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:
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 tables.yaml
file inside the metadata
directory:
- 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:
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"
}
}
}
}
Array session variables in permission rules
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
tables.yaml
file inside the metadata
directory:
- 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:
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."
Array and object relationships work similarly
- 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'
id
is 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 tables.yaml
file
inside the metadata
directory:
- 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:
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 tables.yaml
file inside
the metadata
directory:
- 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:
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 tables.yaml
file
inside the metadata
directory:
- 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:
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 tables.yaml
file
inside the metadata
directory:
- 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
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.
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.
Supported from
Back-end only permissions for update
and delete
mutations are supported in Hasura GraphQL engine versions v2.8.0
and above.
Additional Resources
Enterprise Grade Authorization - Watch Webinar.