AuthZed Product Documentation
Restricted API Access

Restricted API Access

Restricted API Access is functionality exclusive to AuthZed products that restricts access to SpiceDB for API Tokens.

This functionality enables organizations to apply the principle of least-privilege to services accessing SpiceDB. For example, read-only tokens can be created for services that should never need to write to SpiceDB.

Those familiar with configuring IAM on the major cloud providers should feel comfortable with the basic concepts:

  • Service Accounts
  • Tokens
  • Roles
  • Policies

Service Accounts

Service Accounts represent your unique workloads. We recommend creating a Service Account for each application that will access the SpiceDB API.

By default Service Accounts have no access to the SpiceDB API; you must apply a Role to gain access.


Tokens are long-lived credentials for Service Accounts. SpiceDB clients must provide a Token in the Authorization header of an API request to perform actions granted to the Service Account.

Service Accounts can have an arbitrary number of Tokens.

We recommend deploying new Tokens before deprovisioning any old Tokens to avoid downtime.

Token Format

The entire contents of a Token is considered secret.

Tokens come in the form of {optional_prefix_with_many_underscores}_{key}.

In open source SpiceDB, the contents of the prefix can be changed without invalidating the token. This is also true of AuthZed products, but we do not recommend it. Features in AuthZed products make assumptions about tokens (such as the how they're logged in Audit Logs).

Here's an example Token from a SpiceDB Dedicated deployment:


To create a Token, you can use the following command:

printf "sdbst_h256_%s\n" $(echo -n thisisnotaverysecuresecret | sha256sum | cut -d' ' -f1)

This should output:



Roles define rules for accessing the SpiceDB API. Roles are bound to Service Accounts to apply those rules to all API Tokens representing the Service Account.

Each rule is composed of an SpiceDB API method (e.g. CheckPermissions, WriteRelationships) and an optional CEL expression (opens in a new tab). Rules are evaluated at request-time and CEL expressions are provided the request payload in order to dynamically evaluate each request.

Any public SpiceDB API type is available to the CEL expression so that you can traverse any type and its fields using language operators. For more details on CEL's language definition, refer to CEL language specification (opens in a new tab).

The following variables are provided the CEL expression varying based on the request method:

  • WriteRelationshipsRequest
  • ReadRelationshipsRequest
  • DeleteRelationshipsRequest
  • WriteSchemaRequest
  • ReadSchemaRequest
  • CheckPermissionRequest
  • LookupResourcesRequest
  • LookupSubjectsRequest
  • ExpandPermissionTreeRequest
  • WatchRequest

Example Rule Expressions

Resource-type Write Limit

This CEL expression disables the ability for writes to occur on anything but the provided resource type.

This is useful for limiting an application to only be able to perform writes to SpiceDB for the type objects that it owns.

WriteRelationshipsRequest.updates.all(x, x.relationship.resource.object_type == "resource")

Subject-type Write Limit

This CEL expression disables the ability for writes to occur on anything but the provided subject type.

WriteRelationshipsRequest.updates.all(x, x.relationship.subject.object.object_type == "user")

Create-only Write Limit

This CEL expression disables the ability for writes to perform updates; they can only create new relationships.

  x.operation == authzed.api.v1.RelationshipUpdate.Operation.OPERATION_CREATE,

Resource-type Read Limit

This CEL expression limits the ReadRelationships API from being able to list anything but the a specific resource type.

ReadRelationshipsRequest.relationship_filter.resource_type == "resource"

Blocking Schema Writes

This CEL expression prevents any schema writes that contain the substring "blockchain". This example could be extended to prevent PII or undesirable patterns from reaching a production schema.


Limit Checks to one Permission

This CEL expression limits CheckPermissions requests to only be able to check a particular permission.

CheckPermissionRequest.permission == "admin"


Policies are what bind Roles to a Service Account.

Each policy is composed of a unique identifer for the policy itself, the principal (the target of the role assignment), and any roles being assigned.

Static Configuration

Enterprise builds of SpiceDB can have their API access configured statically with a YAML configuration file.


These configuration files contain hashes of Tokens and should be treated like secrets.

This functionality is configured with the following flags:

  • --extender-authzed-fgam-endpoint
  • --extender-authzed-fgam-preshared-key

Here's an example showcasing the structure of static configuration:

  - id: "admin"
      authzed.v1/ReadSchema:           ""
      authzed.v1/WriteSchema:          ""
      authzed.v1/ReadRelationships:    ""
      authzed.v1/WriteRelationships:   ""
      authzed.v1/DeleteRelationships:  ""
      authzed.v1/CheckPermission:      ""
      authzed.v1/LookupResources:      ""
      authzed.v1/LookupSubjects:       ""
      authzed.v1/ExpandPermissionTree: ""
      authzed.v1/Watch:                ""
  - id: "my_microservice"
      - id: "token_01"
        hash: "71c73ba92f2032416b18a4f4fffb2a825755bea6a8430f2622ab1f3fb35a10d0"
      - id: "token_02"
        hash: "fcdfc4fa3c5c7381789d90c3c67f6cebf151cbf7e7555e91e77be2aa3e0a4bdf"
  - id: "microservice_with_admin"
    principal_id: "my_microservice"
    principal_type: "service_account"
      - "admin"

Enabling without downtime

If you want to apply a static configuration to an existing SpiceDB cluster without downtime, you must conduct an upgrade process with the following steps:

  1. Create pre-shared keys that follow the token format for each client of your SpiceDB instance. You should add those to your SpiceDB instance configuration. You can do this by defining multiple PSKs via the ENV or flags as comma separated values.
  2. Update all your clients to use those new PSKs.
  3. Prepare the FGAM configuration YAML. This process heavily depends on what each client needs:
    1. You may want to start with FGAM tokens bound to a admin-like Role, since that's what the original PSKs effectively were. This is probably lower risk, and then from there you can move to start trimming down permissions.
    2. Or you may want to move directly to downscoped tokens for your individual services, creating the tokens you need. This may be simple if you have few clients, but more complex as the number of clients grow, and with a bigger blast radious of impact on rollout.
  4. Deploy SpiceDB with the new configuration
© 2024 AuthZed.