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 with id title and user_id columns, and you want users to only access their own posts. This is how you would do it:

Permission Variables

The permission above makes sure users can only select their own posts, because the value of user_id must be equal (_eq) to the authenticated user's 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. The permission variable comes from the access token that all authenticated users have. You can add custom permission variables to create more complex permission rules unique to your project.

Permission Variables

You can add permission variables in the Nhost Dashboard under Settings -> Roles and permissions -> Permission Variables. These permission variables are automatically added to users' access tokens. This way, permission variables are available when creating permissions for your GraphQL API.

Permission Variables

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

query {
user(id: "<user-id>") {
company {
id
}
}
}

Arrays

You must add [] at the end of the path for permission variables that are arrays.

Example: Let's say you have a permission variable x-hasura-organization-ids, the path should be, e.g., user.profile.organizations.id[].

This will result in the following GraphQL query internally:

query {
user(id: "<user-id>") {
profile {
organizations {
id
}
}
}
}

And result in the following permission variable:

{
"x-hasura-organization-ids": "{\"13\",\"37\"}"
}

Limitation on JSON/JSONB columns

JSON columns cannot be used in custom claims, except the users.metadata column.

Local Permission Variables

To use permission variables locally, add your claims to the config.yml.

Example: Add a permission variable x-hasura-organization-id:

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

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

✅ Correct:

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

🛑 Incorrect:

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

Roles

Every GraphQL request resolves permissions using a single role.

Default Role

Every user has one default role. The default role is used to resolve permissions if no role is specified using the x-hasura-role header in the GraphQL request. The user is the default role for authenticated users.

Allowed Roles

Every user also has an array of 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 and Unauthenticated Users

GraphQL requests from unauthenticated users resolve permissions using the public role.

Insert Permissions

Insert permissions

Here is a popular approach for insert permission for authenticated 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 that's the only column that should be inserted by the user. The id is automatically generated by the database and user_id is set using a column preset.
  4. Under Column presets, set user_id to x-hasura-user-id. This way, every new record's user_id value is set to the ID of the user making the request.

Now, authenticated users are allowed to insert posts. Users are allowed to 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 follow the same pattern. Here's an example of how to add select permissions:

Select permissions

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

  1. Go to the Database section in the Nhost Dashboard.
  2. In the context menu of the table you want to edit, click on Edit Permissions.
  3. Click on the role and operation you want to set.
  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.
  6. Limit the number of rows to 100 (or some other relevant number).
  7. Select the columns you want the user to be able to read. In our case, we'll allow the user to read all columns.
  8. Click Save.

Known issues

Permissions are slow

In certain situations, permission checks can cause significant delays. One way to identify this issue is by comparing the execution time of a GraphQL query when performed as an admin versus as a regular user. To resolve such cases, disabling the Just-in-Time (JIT) compilation in Postgres can be beneficial.

Github issue

Next Steps

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