Skip to main content

Permissions

The GraphQL API is protected by a role-based permission system.

For each role, you create rules for the select, insert, update, and delete operations.

Example: Let's say you have a posts table, and you want users to only access their own posts. This is how you would do it:

Posts Table
CREATE TABLE "public"."posts" (
"id" serial NOT NULL PRIMARY KEY,
"title" text NOT NULL,
"user_id" uuid NOT NULL,
);
Hasura Permission Rule
{
"user_id": {
"_eq": "X-Hasura-User-Id"
}
}

The rule above make it so users can only select posts where the value of user_id is equal (_eq) to their user ID (x-hasura-user-id).

What is x-hasura-user-id?

x-hasura-user-id is a permission variable that is used to create permission rules in Hasura. The permission variable comes from the access token that signed-in users have.

The x-hasura-user-id permission variable is always available for all signed-in users. You can add custom permission variables to create more complex permission rules unique to your project.

Custom Permission Variables

You can add custom permission variables in the Nhost console under Users and then Roles and permissions. These permission variables are then available when creating permissions for your GraphQL API in the Hasura console.

Permission Variables

Example: Let's say you add a new permission variable x-hasura-organisation-id with path user.profile.organisation.id. This means that Nhost Auth will get the value for x-hasura-organisation-id by internally generating the following GraphQL query:

query {
user(id: "<User's ID>") {
profile {
organisation {
id
}
}
}
}

Local Custom Permission Variables

To use custom permission variables locally, add your claims to the config.yml as following:

auth:
jwt:
custom_claims: '{"organisation-id":"profile.organisation.id"}'

Your custom claim will be automatically prefixed with x-hasura-, therefore, the example above results in a custom permission variable named x-hasura-organisation-id.

caution

The custom claim path should not start with user when being defined in the config.yaml file.

✅ Correct:

custom_claims: '{"organisation-id":"profile.organisation.id"}'

🛑 Incorrect:

custom_claims: '{"organisation-id":"user.profile.organisation.id"}'

Limitation on JSON/JSONB columns

JSON columns cannot be used in custom claims, with the exception of the users.metadata column.

Arrays

When the target value is expected to be an array, it is important to explicitly add a [] at the end of the expression. For instance: if organisationIds is expected to be an array, you must set the expression to organisationIds[]. It will otherwise return a litteral when the array is a singleton.

✅ Singleton array with '{"organisation-ids":"organisationIds[]"}'

{
"x-hasura-organisation-ids": "{\"org-id-1\"}"
}

🛑 Singleton array with '{"organisation-ids":"organisationIds"}'

{
"x-hasura-organisation-ids": "org-id-1"
}

Roles

Every GraphQL request is resolved based on a single role. Roles are added in the Hasura Console when selecting a table and clicking Permissions.

If the user is not signed in, the GraphQL API resolves permissions using the public role.

Default Role

Every user have one default role. The default role is used to resolve permissions if no other role is specified using the x-hasura-role header in the GraphQL request. By default, the default role is user for signed-in users.

Allowed Roles

Every user also has a one or more allowed roles. Allowed roles are roles that the user is allowed to use to override the default role when making a GraphQL request. To override the default role, add a header x-hasura-role = <role> to the GraphQL request.

Public Access

GraphQL requests from unauthenticated users are resolved using the public role.

Insert permissions

Insert permissions

Here is a popular approach for insert permission for signed-in users.

  1. At the top of the page, click "insert" on the "user" role.
  2. Select "Without any checks".
  3. Select the columns you want to allow users to insert.

In our example, we only mark title, because the other columns should not be inserted by the user.

We also want every new record's user_id value to be set to the ID of the user making the request. We can tell Hasura to do this using Column presets.

  1. Under Column presets, set user_id to x-hasura-user-id.

Now, users who are signed-in can insert posts. Users can add a title when inserting a post. The post's id is automatically generated by the database and the user_id is automatically set to the user's id using the user_id = x-hasura-user-id column preset.

Select, Update and Delete Permissions

Select, update, and delete permissions usually follows the same pattern. Here's an example of how to add select permissions:

Select permissions

One of the most common permission requirements is that signed-in users should only be able to read their own data. This is how to do that:

  1. Go to Hasura Console
  2. Select your table and open the Permissions tab
  3. At the top of the page, click "select" on the "user" role.
  4. Select "With custom check" to create a new rule
  5. Enter user_id, _eq and x-hasura-user-id into the rule form.

This means that in order for users to read data, the user ID value in the database row must be the same as the user ID in the access token.

To further refine this rule, do the following:

  1. Limit number of rows to 100 (or some other relevant number).
  2. Select the columns you want the user to be able to read. In our case we'll allow the user to read all columns.

Note that if you add columns to your table table later, you must check new columns here to let users read them.

Next Steps

Hasura has more in-depth documentation related to permissions that you can learn from: