Check out v4 of the Fauna CLI

v4 of the Fauna CLI is now in beta.

The new version introduces enhancements to the developer experience, including an improved authentication workflow. To get started, check out the CLI v4 quick start.

Roles

Reference: FSL role schema

Fauna uses secrets for authentication and authorization. Roles determine a secret’s privileges, which control data access.

Role types

Fauna supports two types of roles:

Built-in roles

Built-in roles grant access to all of a database’s resources. Built-in roles are assigned to keys and typically used for system processes. You can’t assign built-in roles to tokens or JWTs.

Built-in role Privileges

admin

Full access to a database, including all:

  • Collections, including their documents and indexes

  • Access providers (but not their JWTs' secrets)

  • Child databases

  • Keys (but not their secrets)

  • Schema, including .fsl schema files

  • Tokens (but not their secrets)

  • User-defined functions (UDFs)

  • User-defined roles

You can also create an admin key in a Fauna account’s top-level context. This key lets you create and manage top-level databases.

server

Same as admin, except the server role can’t access:

  • Access providers

  • Child databases

  • Keys

  • User-defined roles

server-readonly

Same as server, except the server-readonly only has read privileges.

client

Deprecated. Do not use.

User-defined roles

User-defined roles can grant:

You create and manage user-defined roles as FSL role schema:

role manager {

  // Assign the `manager` role to tokens with
  // an identity document in the `Manager` collection.
  // Not applicable to JWTs or keys.
  membership Manager

  // If the predicate is `true`,
  // assign the `manager` role to tokens with
  // an identity document in the `Customer` collection.
  membership Customer {
    // Check that the identity document's
    // `accessLevel` field value is `manager`.
    predicate (customer => customer.accessLevel == 'manager')
  }

  // Grant `read` access to the `Customer` collection,
  // including its documents and indexes.
  privileges Customer {
    read
  }

  // Grant full access to the `OrderItem` collection.
  privileges OrderItem {
    create
    read
    write
    delete
  }

  // If the predicate is `true`,
  // grant `create` access to the `Order` collection.
  privileges Order {
    create {
      predicate (doc =>
        // Check the order's `status` field.
        doc.status == "cart"
      )
    }
  }

  // If the predicate is `true`,
  // grant `read` access to the `Manager` collection.
  privileges Manager {
    read {
      // Check that the `Manager` document
      // is the token's identity document.
      // `Query.identity()` is `null` for JWTs or keys.
      predicate (doc => Query.identity() == doc)
    }
  }

  // If the predicate is `true`,
  // grant `call` access to the
  // user-defined `checkout` function.
  privileges checkout {
    call {
      // Check that the `orderId` belonds to the user.
      // `Query.identity()` is `null` for JWTs or keys.
      predicate ((orderId, status, payment) => {
        let order = Order.byId(orderId)!
        order?.customer == Query.identity()
      })
    }
  }
}

Role collection

Fauna stores user-defined roles as documents in the Role system collection. These documents are an FQL version of the FSL role schema. You can use Role methods to access and manage user-defined roles in FQL.

See Role FQL docs

Membership

Fauna assigns user-defined roles to tokens based on their identity document’s collection and the role’s membership property:

role customer {
  // Assign the `customer` role to tokens with
  // identity documents in the `Customer` collection.
  membership Customer
}

The membership property doesn’t assign roles to JWTs or keys.

Membership predicates

Each membership property can include a predicate.

Membership predicates let you conditionally assign roles to tokens:

role customer {
  // If the predicate is `true`,
  // assign the `customer` role to tokens with
  // identity documents in the `Customer` collection.
  membership Customer {
    // Checks the `status` field in the
    // token's identity document.
    predicate (user => user.status == "active")
  }
}

You can use membership predicates to implement attribute-based access control (ABAC).

See Attribute-based access control (ABAC)

Membership for multiple roles

You can use membership to assign a token up to 64 roles.

For performance, Fauna stops checking a token’s roles once it verifies the token has the privileges required for a query.

Fauna evaluates membership predicates sequentially, prioritizing previously successful ones.

Privileges

A role can grant one or more privileges. A privilege allows a specific action, such as read or write, on a specific resource, such as a collection or UDF.

Privileges act as an allowlist. Roles grant no privileges by default.

Collection privileges

Collection privileges grant access to a collection’s documents. A collection privilege can allow the create, delete, read, or write actions. read access includes the ability to call the collection’s indexes.

role customer {
  // Grant read access to `Product` documents and indexes.
  privileges Product {
    read
  }
}

You can also grant access to system collections that store Fauna resources:

role manager {
  // Grant `create` and `read` access to the `Token` system collection.
  // Allows the role to create token secrets.
  privileges Token {
    create
    read
  }
}

To allow a role to create, delete, or manage user-defined collections themselves, grant access to the Collection system collection:

role manager {
  // Grant full access to the `Collection` system collection.
  // Allows the role to create, delete, read, and update
  // user-defined collections.
  privileges Collection {
    create
    delete
    read
    write
  }
}

Function privileges

Function privileges grant the ability to call a server-side UDF:

role customer {
  // Grants `call` access to the `getOrCreateCart` UDF.
  privileges getOrCreateCart {
    call
  }
}

By default, UDFs run with the same privileges as the query’s authentication secret. You can override this default by specifying an optional role in the UDF’s function schema.

If a role is specified in the function schema, the UDF runs with that role’s privileges, regardless of the authentication secret’s privileges.

See User-defined functions (UDFs)

Privilege predicates

Each privilege action can include a predicate. Privilege predicates let you conditionally grant privileges to a role:

role customer {
  // If the predicate is `true`,
  // grant `write` access to the `Order` collection.
  privileges Order {
    write {
      predicate ((oldDoc, newDoc) =>
        // Disallow write access 10 hours after
        // the original order's last update (`ts`)
        Time.now().difference(oldDoc!.ts, "hours") < 10 &&
        // Check that the user's `country` is
        // in the updated order's `allowedCountries`
        newDoc.allowedCountries.includes( Query.identity()!.country)
      )
    }
  }
}

Privilege predicates are passed different arguments based on their action. See Privilege predicate arguments.

You can use membership predicates to implement ABAC.

See Attribute-based access control (ABAC)

Query-time evaluation

Fauna evaluates a secret’s roles and privileges, including any predicates, at query time for every query. Changes to roles and privileges take effect immediately and affect pre-existing secrets.

Check a secret’s roles

You can use a user-defined collection and UDFs to check a secret’s assigned roles. See Check a secret’s user-defined roles.

Multi-tenancy and scope

Roles are scoped to a single database. A parent database’s roles don’t apply to its peer or child databases.

You can copy and deploy roles across databases using FSL and a CI/CD pipeline. See Manage schema with a CI/CD pipeline.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!