DocsAuthenticationCardinal 0.7.0

Access tokens

A bearer credential for scripts, narrowed by a closed vocabulary of scopes, that can never do what its owner cannot.

llms.txt

A passkey needs a human being and a browser. A backup job at three in the morning has neither, so it carries a token instead:

cardinal token create backup-job -name "nightly backup" \
    -scope identity,applications -for 30d
cardinal token list backup-job          # live ones first
cardinal token revoke backup-job <token-id>

backup-job there is a service account, and that is not incidental. See below.

The value is printed once and never again. Tokens are bounded like grants: the default is 90 days, and the API refuses anything beyond a year.

Scopes are a closed vocabulary

Eight, and there will not be many more. Scopes that describe endpoints multiply with the API until they mean nothing:

Scope What it is for
identity Read who the token belongs to. Reveals nothing the holder did not already have.
applications Reach applications through the proxy. The reason tokens exist.
profile Edit the owner's display name. Rarely wanted.
decisions Read the decision log. Useful to a monitoring job, a map of the organisation to anyone else.
policy Read the active policy set, which is every rule governing every door.
scim Provision accounts. The only scope that writes to the directory.
events Collect security events for a poll receiver.
journal Read the journal's fingerprint and check a kept one. Works only for a token whose owner is in directory-admins or security-admins.

A scope narrows and can never widen. Policy still decides, and a token can never exceed its owner. The scope answers a question Cedar cannot ask, because Cedar sees a principal and not the credential that presented it: was this token issued for this?

Scopes cannot be changed after issue. A narrower token is a new token.

What a token cannot do

It is never device-bound. That single fact does most of the work: the shipped policy refuses administrative actions and SSH certificate issuance to anything that is not a device-bound credential, so a leaked token cannot administer the directory or log into a machine, without a rule anywhere naming tokens.

It cannot touch the credentials that authenticate its owner. Passkey self-service is behind the same device-bound requirement.

Nobody can mint one that acts as another person. A person's own token comes from their own session, and the request body has no say in whose it is, so an administrator who sends somebody else's login gets a token for themselves. A token minted for you by somebody else is a way to act as you, with your name on the audit trail.

An administrator issues tokens for service accounts, and only those. A service account has no passkeys and cannot sign in, so it cannot ask for its own and somebody has to ask on its behalf, and a token acting as a service account is acting as exactly what it says it is. Ask for one for a person and Cardinal refuses, and says where they can make their own.

That is the shape to build integrations around: create a service account for the job, give it the groups it needs, issue it a token.

cardinal service-account create entra-sync
cardinal grant provisioners entra-sync
cardinal token create entra-sync -name "Entra SCIM" -scope scim

Listing and revoking are not the same question. An administrator can list and end anybody's tokens, person or service account, because neither hands out a credential and ending one in the middle of an incident is exactly the job.

In the console

Access → Tokens is the self-service view: create one, choose its scopes and lifetime, copy the value the one time it is shown, revoke one. It shows the same tokens the CLI lists, because both go through the same API. There is no console view for issuing a service account's token yet; that is CLI-only, and the value is shown exactly once either way.

Best for

  • CI jobs and cron work that call an internal service sitting behind forwardAuth.
  • An identity provider provisioning accounts over SCIM.
  • A security event receiver that collects rather than being pushed to.

The trade-off

A bearer token is a string that grants access to whoever holds it, which is everything passkeys were chosen to avoid. Cardinal's answer is not to pretend otherwise: tokens are bounded, scoped, revocable, listed where their owner can see them, and structurally incapable of the privileged actions. If a token leaks, the blast radius is its scope and its owner's ordinary access, not the directory.

Limits

  • No refresh, no rotation. A token expires and a new one is created.
  • No per-token IP or hostname restriction.
  • Scopes are not per-application. A token with applications may reach any application its owner's policy permits, not a chosen one.
  • A token is not an OIDC credential. It authenticates its owner to Cardinal and to applications behind the proxy. An application that speaks OIDC gets its own tokens through that flow instead.