Auth Rules

All rules are global. They apply to all queries and mutations, or permitted operations unless otherwise configured differently with model-level rules/field-level rules.

Grafbase supports the following strategies to control access to data:

  • Anonymous — Allow access with any valid API key
  • Signed-in user — Allow access to any signed-in user
  • Group-based — Allow acces to users of a group

The rules below work with all the available auth providers.

You can configure anonymous access to data. This rule is enabled by default and can't be disabled.

This means anyone with a valid API key can read/write data:

schema @auth(rules: [{ allow: anonymous }]) {
  query: Query
}

You can configure signed-in access to data using a valid provider:

schema
  @auth(
    providers: [{ type: oidc, issuer: "{{ env.ISSUER_URL }}" }]
    rules: [{ allow: private }]
  ) {
  query: Query
}

You can configure group-based access to data based on the groups claim of a valid JWT:

schema
  @auth(
    providers: [{ type: oidc, issuer: "{{ env.ISSUER_URL }}" }]
    rules: [{ allow: groups, groups: ["backend", "admin"] }]
  ) {
  query: Query
}

The user only has access if the JWT claims contain one of the allowed groups. The following decoded JWT contains a valid groups value admin:

{
  "exp": 1659646197,
  "groups": ["admin"],
  "iat": 1659559797,
  "iss": "https://clerk.b74v0.5y6hj.lcl.dev",
  "nbf": 1659559792,
  "sub": "user_12345"
}

You can optionally set groupsClaim for group-based auth to use a custom claim path.

Consider the following JWT provided by your issuer:

{
  "header": {
    "typ": "JWT",
    "alg": "RS256"
  },
  "payload": {
    "https://grafbase.com/jwt/claims": {
      "x-grafbase-allowed-roles": ["editor", "user", "mod"]
    }
    // ...
  }
}

Here the groups claim x-grafbase-allowed-roles is nested inside of https://grafbase.com/jwt/claims. This is declared using .. You can provide a groupsClaim path along with the provider:

schema
  @auth(
    providers: [
      {
        type: oidc
        issuer: "{{ env.ISSUER_URL }}"
        groupsClaim: "https://grafbase\\.com/jwt/claims.x-grafbase-allowed-roles"
      }
    ]
  ) {
  query: Query
}

Any . used inside of URLs will need to be escaped for the groupsClaim value.

You can set rules globally by using the @auth directive on schema:

schema
  @auth(
    providers: [{ type: oidc, issuer: "{{ env.ISSUER_URL }}" }]
    rules: [{ allow: private }]
  ) {
  query: Query
}

You can configure rules on a per-model basis using the @auth directive:

type User
  @model
  @auth(
    rules: [
      { allow: private, operations: ["read"] }
      { allow: groups, groups: ["admin"] }
    ]
  ) {
  name: String!
}

You can configure rules on a per-field basis using the @auth directive:

type User @model @auth(rules: [{ allow: private }]) {
  id: ID!
  title: String!
  password: String @auth(rules: [{ allow: groups, groups: ["admin"] }])
}

There are a few things to consider when creating field-level rules:

  • You can't create entities with any field you can't create
  • You can't delete entities with any field you can't delete
  • You can't link/unlink entities without being able to read the entity id
  • You can't request any fields to be returned by queries or mutations you can't read

You can restrict access to specific operations using these operation rules:

  • get — Allow to query a single entity
  • list — Allow to query entity collections
  • read — Combines both get and list
  • create — Allow create mutations
  • update — Allow update mutations
  • delete — Allow delete mutations
schema
  @auth(
    providers: [{ type: oidc, issuer: "{{ env.ISSUER_URL }}" }]
    rules: [{ allow: private, operations: ["get"] }]
  ) {
  query: Query
}

You can also set separate rules for operations.

The following authorization enables:

  • Signed-in users to perform read operations
  • Users of the moderator group to perform update operations
  • Users of the admin group to perform all operations
schema
  @auth(
    providers: [{ type: oidc, issuer: "{{ env.ISSUER_URL }}" }]
    rules: [
      { allow: private, operations: ["read"] }
      { allow: groups, groups: ["moderator"], operations: ["update"] }
      { allow: groups, groups: ["admin"] }
    ]
  ) {
  query: Query
}
  • Model rules replace global rules.
  • Field rules replace model/global rules.
Was this page helpful?