Skip to content

Configuring the authorization mode

The authz key of the SystemAuth configuration selects how authorization is evaluated. Both modes implement the same contract (organization roles, application roles, resource grants, ListResources), so switching is a configuration change. The design is in Authorization.

Modes

authz.mode Evaluates Needs
rbac (default) Roles and direct grants in process, from the membership, role and grant tables Nothing else
rebac Permissions derived through relationships by an engine A relationship engine; spicedb is the only one
authz:
  mode: rebac
  engine: spicedb        # default; rebac only
  spicedb:
    mode: remote         # embedded (default) | remote
    endpoint: spicedb.internal:50051
    token: ${SPICEDB_TOKEN}
    write_schema: false  # remote only
Key Default Meaning
mode rbac rbac or rebac
engine spicedb Only with rebac
spicedb.mode embedded embedded runs in process; remote connects over gRPC
spicedb.datastore_engine memory Embedded only: memory or postgres
spicedb.datastore_uri Embedded postgres only; required there
spicedb.endpoint, spicedb.token Remote only; endpoint required
spicedb.insecure false Remote without TLS; development only
spicedb.write_schema false Remote only: write the composed schema at startup. Embedded instances always get it

Building the provider

res, err := mode.New(ctx, cfg.Authz, mode.Deps{DB: db, Registry: registry})
if err != nil { return err }
defer res.Close()

orgs := organization.NewService(db, organization.WithAuthzSyncer(res.Syncer))
invites := invite.NewService(db, baseURL,
    invite.WithAuthzSyncer(res.Syncer), invite.WithResourceGrants(res.Grants))

mode.New applies defaults, validates, and for rebac starts or connects to the engine and writes the schema composed from the registered vocabularies. Result carries Provider, Syncer, Grants and Close(). The membership, role and grant tables remain the record in both modes; under rebac the services mirror each change into the graph.

Deps also takes SyncMode (strict returns a graph write failure, eventual, the default, logs it), AccessChangeSink, Logger, PlatformAdmin, ManagerRoles and RBACOptions.

Switching from rbac to rebac

A deployment that switches starts with an empty graph. Write the existing memberships, application roles and grants through the syncer before serving the first request; no bulk rebuild command ships yet.

Errors

Configuration errors name the key and the accepted values and wrap systemauth.ErrInvalidConfig when loaded through SystemAuth:

Message Cause
authz: unknown mode "..." (want rbac or rebac) Mode misspelled
authz: engine "..." is set but mode is rbac Engine given with rbac
authz: spicedb settings are given but mode is rbac SpiceDB block with rbac
authz: unknown engine "..." for mode rebac Engine not supported
authz: spicedb.mode remote requires spicedb.endpoint Remote without an endpoint
authz: spicedb.endpoint and spicedb.token apply to spicedb.mode remote, not embedded Remote keys on an embedded instance
authz: spicedb.datastore_engine postgres requires spicedb.datastore_uri Embedded postgres without a URI
authz/mode: Deps.DB is required mode.New called without a database

At runtime, an organization API without an Authorizer answers 501, and a caller who lacks a permission answers 403 (or 404 when they cannot even view the organization).

Package paths

The role-based provider is authz/rbac and the relationship provider authz/rebac/spicedb. The former authz/simple and authz/spicedb paths are deprecated forwarders and will be removed in the next major release.