Skip to main content
Version: Next

Offline Access

By default, a Backstage user token is short-lived. Clients that sign in through the auth backend's OAuth flow, such as the Backstage CLI and MCP clients, can also ask for offline access with the offline_access scope. They then receive a refresh token, which lets them get new user tokens without the user signing in again.

Each refresh token belongs to an offline session that is stored in the auth backend database.

Enabling offline access​

Offline access is turned off by default. Enable it in your app-config.yaml:

app-config.yaml
auth:
experimentalRefreshToken:
enabled: true

When it is turned off, clients that ask for the offline_access scope still sign in, but they do not receive a refresh token.

Configuring session lifetimes​

The following options are available under auth.experimentalRefreshToken:

OptionDefaultDescription
tokenLifetime30 daysHow long a refresh token stays valid without being used. Each use replaces the refresh token with a new one.
maxRotationLifetime1 yearThe maximum lifetime of a session, no matter how often it is used. After this, the user must sign in again.
maxTokensPerUser20The maximum number of sessions per user. When the limit is reached, the least recently used session is removed.
dangerouslyDisableCatalogPresenceCheckfalseTurns off the check that the user still exists in the catalog when a token is refreshed. See below.

A client gets at most one session per user. Signing in again with the same client replaces its previous session.

Ending sessions​

Signing out from a client​

A client can revoke its own refresh token through the standard revocation endpoint, /api/auth/v1/revoke. The request must identify the client with its client_id. Clients that were registered through dynamic client registration must also authenticate with their client secret.

Revoking all sessions of a user​

Other backend services can revoke all offline sessions of a user at once, for example when an administrator needs to sign a user out of every client. Send a POST request to /api/auth/v1/offline-sessions/revoke with the user entity reference in the body:

{ "userEntityRef": "user:default/jane.doe" }

The response contains the number of revoked sessions, for example { "revokedCount": 2 }. Every revocation is recorded as an audit event.

Only service credentials are accepted, so users cannot call this endpoint directly. The calling service is responsible for checking that the request is allowed, for example by only exposing it to administrators.

Users removed from the catalog​

When a token is refreshed, the auth backend checks that the user entity still exists in the catalog. If it does not, the session is revoked and the refresh fails. If your Backstage instance allows sign-in without users in the catalog, you can set dangerouslyDisableCatalogPresenceCheck to turn off this check. With this check disabled, sessions of removed users stay valid until they expire.

Access tokens that were already issued​

Revoking a session stops the client from getting new user tokens. User tokens that were already issued stay valid until they expire. You can shorten how long they are valid with auth.backstageTokenExpiration.