Tokens

Reference: Token

A token is a type of authentication secret used to provide identity-based access to a Fauna database.

You typically create and use tokens as part of a Fauna-based end-user authentication system.

Token system collection

Fauna stores tokens as documents in the Token system collection. You can use Token methods to access Token collection documents in FQL.

See Token FQL docs

Identity documents

Each token is associated with an identity document that represents an end user, system, or other identity. The identity document is distinct from the Token document.

Any document in any user-defined collection can act as an identity document. For example:

// Example `Customer` collection document that acts
// as an identity document.
{
  id: "<DOCUMENT_ID>",
  coll: Customer,
  ts: Time("2099-07-08T13:39:55.690Z"),
  firstName: "Alice",
  lastName: "Appleseed",
  email: "alice.appleseed@example.com",
  address: {
    street: "87856 Mendota Court",
    city: "Washington",
    state: "DC",
    zipCode: "20220"
  },
  ...
}

Multiple identity document collections

A common approach is to use different collections for different types of identity documents. This often makes role membership easier to manage.

For example, you can use the Customer collection to store identity documents for customer end users. In the same database, you can use the Manager collection to store identity documents for manager end users.

Token roles

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

// Schema for the user-defined `customer` role.
role customer {
  // Assign the `customer` role to tokens with
  // identity documents in the `Customer` collection.
  membership Customer
}

You can use membership to assign a token multiple roles. You can also use membership predicates to conditionally assign roles to tokens.

You can’t assign a built-in role to a token.

See Role membership.

Update a token’s roles

Fauna checks a token’s roles and related privileges at query time for every query.

To update a token’s roles or privileges, edit the membership and privileges for the related roles. Changes to roles and privileges take effect immediately and affect pre-existing tokens.

Check a token’s roles

You can use user-defined functions (UDFs) to check a token’s roles. See Check a secret’s user-defined roles.

Token scope

Each token is scoped to a specific Fauna database. You can’t use a token to access parent or peer databases.

Credentials

A credential associates an end-user password with an identity document.

Fauna stores credentials as documents in the Credential system collection. You can use Credential methods to access Credential collection documents in FQL.

See Credential FQL docs

Create and manage tokens

You create and manage tokens using FQL queries.

Fauna supports two methods for token creation:

Create a token with a credential

The following procedure outlines the steps for creating a token with a credential.

For clarity, the procedure outlines each step separately. In production, you’d typically bundle and encapsulate the steps in user-defined functions (UDFs). For an example, see Build an end-user authentication system.

  1. If needed, create an identity document:

    // Creates `Customer` collection document.
    // The collection contains identity documents for
    // customer end users.
    Customer.create({
        email: "jdoe@example.com"
      })
  2. Create a credential for the identity document:

    // Declares a `customer` variable.
    // Uses the `Customer` collection's `byEmail()` index to
    // get `Customer` collection documents by `email` field value.
    // In the `Customer` collection, `email` field values are unique
    // so return the `first()` (and only) document.
    let customer = Customer.byEmail("jdoe@example.com").first()
    
    // Creates a credential for the previous `Customer`
    // identity document. In this example, the `password` is a
    // provided by the customer end user.
    Credential.create({
        document: customer,
        password: "sekret"
    })

    An identity document can only have one credential.

  3. Call login() to create a token using the credential and its password:

    let customer = Customer.byEmail("jdoe@example.com").first()
    
    // Uses `byDocument()` to get the credential for
    // the previous `Customer` identity document.
    let credential = Credentials.byDocument(customer)
    
    // Calls the `login()` with the credential's password.
    credential?.login("sekret"))

    The returned Token document includes the token’s secret, which you can use to authenticate with Fauna. A token’s secret is shown once — when you create the token.

    {
      id: "<DOCUMENT_ID>"",
      coll: Token,
      ts: Time("2099-07-08T14:34:15.520Z"),
      // Token's secret
      secret: "fn...",
      // `document` contains the token's identity document.
      document: Customer("<IDENTITY_DOCUMENT_ID>")
    }
  4. If wanted, you can call login() multiple times to create multiple tokens using the same credential.

Reference: login()

Create a token without a credential

The following procedure outlines the steps for creating a token without a credential or related password.

  1. If needed, create an identity document:

    // Creates `Customer` collection document.
    // The collection contains identity documents for
    // customer end users.
    Customer.create({
        email: "jdoe@example.com"
      })
  2. Call Token.create() to create a token using the identity document:

    // Declares a `customer` variable.
    // Uses the `Customer` collection's `byEmail()` index to
    // get `Customer` collection documents by `email` field value.
    // In the `Customer` collection, `email` field values are unique
    // so return the `first()` (and only) document.
    let customer = Customer.byEmail("jdoe@example.com").first()
    
    // Creates a token for the previous `Customer`
    // identity document.
    Token.create({
      document: customer
    })

    The returned Token document includes the token’s secret, which you can use to authenticate with Fauna. A token’s secret is shown once — when you create the token.

    {
      id: "<DOCUMENT_ID>"",
      coll: Token,
      ts: Time("2099-07-08T14:34:15.520Z"),
      // Token's secret
      secret: "fn...",
      // `document` contains the token's identity document.
      document: Customer("<IDENTITY_DOCUMENT_ID>")
    }
  3. If wanted, you can call Token.create() multiple times to create multiple tokens using the same identity document.

Reference: Token.create()

Multiple requests

You can use the same token secret to authenticate multiple Fauna requests. A secret remains valid until it expires or is deleted.

Token expiration

A Token document can include an optional ttl (time-to-live) field that contains the token’s expiration timestamp. You can set this ttl when you create a token using login():

let customer = Customer.byEmail("alice.appleseed@example.com").first()
let credential = Credentials.byDocument(customer)

// Set the token's `ttl` to 60 minutes from the current time at
// query. The token's secret expires at its `ttl`.
credential?.login("fauna-demo", Time.now().add(60, "minutes")))
{
  id: "<TOKEN_DOCUMENT_ID>"",
  coll: Token,
  ts: Time("2099-07-08T14:34:15.520Z"),
  ttl: Time("2099-07-06T19:28:51.499944Z"),
  secret: "fn...",
  document: Customer("<IDENTITY_DOCUMENT_ID>")
}

You can also set ttl using Token methods:

Token.byId("<TOKEN_DOCUMENT_ID>")?.update({
  // Set the token's `ttl`.
  ttl: Time.now().add(60, "minutes")
})

After the ttl timestamp passes, Fauna permanently deletes the token and its secret. You can’t use an expired token’s secret to authenticate requests.

A Token document without a ttl does not expire and persists until deleted.

Recover a lost token secret

You can’t recover or regenerate a lost token secret. After creation, Token documents don’t include the token’s secret. Instead, delete the token and create a new one.

Access end-user data in a query

If you use a token secret to authenticate a FQL query, you can access the token’s identity document or Token document in the query.

You can use ABAC to dynamically grant roles and privileges based on attributes of these documents.

Access a token’s identity document

Use Query.identity() to get the identity document for a query’s authentication token:

Query.identity()
{
  id: "<DOCUMENT_ID>",
  coll: Customer,
  ts: Time("2099-06-21T18:39:00.735Z"),
  firstName: "Alice",
  lastName: "Appleseed",
  email: "alice.appleseed@example.com",
  ...
}
Reference: Query.identity()

Access a token document

Use Query.token() to get the Token document for a query’s authentication token:

Query.token()
{
  id: "<DOCUMENT_ID>",
  coll: Token,
  ts: Time("2099-07-06T19:11:13.570Z"),
  document: Customer.byId("<IDENTITY_DOCUMENT_ID>")
}
Reference: Query.token()

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!