Access control examples

This is a guide to help you set up a basic authorization architecture for your GraphQL fields.

Here are some examples of common use-cases.

Anonymous (not logged in) users

  • Create a role called anonymous (this value is up to you, you could even name the role public).
  • Generally, you wouldn’t add insert, update, or delete permissions.
  • For the select permission condition, create a valid condition depending on your data model. For example, is_published: {_eq: true}.
  • If you don’t have a condition, then just set the permission to Without any checks, represented by a {}.
  • Choose the right set of columns that will get exposed in the GraphQL schema as fields. Ensure that sensitive information will not be exposed.

You can use the env variable HASURA_GRAPHQL_UNAUTHORIZED_ROLE or --unauthorized-role flag to set a role for non-logged in users. The configured unauthorized role will be used whenever an access token is not present in a request to the GraphQL API.

Logged-in users

  • Create a role called user.
  • Access control rules in this case are usually dependent on a user_id or a owner_id column in your data model.
  • Set up a permission for insert/select/update/delete that uses said column. E.g.: author_id: {_eq: "X-Hasura-User-Id"} for an article table.
  • Note that the X-Hasura-User-Id is a dynamic session variable that comes in from your auth webhook’s response, or as a request as a header if you’re testing.

Managers of an organisation in a multi-tenant app

Suppose you have a multi-tenant application where managers of a particular organisation can see all of the data that belongs to the organisation. In this case, your data models will probably have an org_id column that denotes the organisation either in the same table or via a related table.

  • Create a role called manager.
  • Create a permission for select, which has the condition: org_id: {_eq: "X-Hasura-Org-Id"}.
  • X-Hasura-Org-Id is a dynamic variable that is returned by your auth webhook for an incoming GraphQL request.

Collaborators of an article

Let’s say the “ownership” or “visibility” information for a data model (table) is not present as a column in the table, but in a different related table. In this case, let’s say there is an article table and a collaborator table that has article_id, collaborator_id columns.

  • Create a relationship called collaborators from the article table.
    • Array relationship (article has array of collaborators): article :: id collaborator :: article_id.
  • Create a role called collaborator.
  • Create a select permission on the article table, which has the condition: collaborators: {collaborator_id: {_eq: "X-Hasura-User_id"}}.
    • This reads as: Allow the role collaborator to select if article.collaborators has a collaborator_id equal to that of X-Hasura-User-Id.

Role-based schemas

For every role that you create, Hasura automatically publishes a different GraphQL schema that represents the right queries, fields, and mutations that are available to that role.

Case 1: Logged-in users and anonymous users can access the same GraphQL fields

In simple use-cases, logged-in users and anonymous users might be able to fetch different rows (let’s say because of a is_public flag), but have access to the same fields.

  • anonymous role has a {is_public: {_eq: true}} select condition.
    • This reads: Allow anyone to access rows that are marked public.
  • user role has a _or: [{is_public: {_eq: true}}, {owner_id: {_eq: "X-Hasura-User-Id"}}].
    • This reads: Allow users to access any rows that are public, or that are owned by them.

Case 2: Logged-in users and anonymous users have access to different fields

In this case, anonymous users might have access only to a subset of fields while logged-in users can access all the fields for data that they own.

  • anonymous role has a {is_public: {_eq: true}} select condition, and only the right columns are allowed to be selected.
    • This reads: Allow anyone to access rows that are marked public.
  • user role has a {owner_id: {_eq: "X-Hasura-User-Id"}} and all the columns are marked as selected.
    • This reads: Allow users to that are owned by them.