Home/Integration/User-plane tokens ENУКРРУС API Reference (ReDoc) ↗

User-plane tokens

Exchange a login session for a short-lived token scoped to this service, and how roles map.

The user plane accepts exactly one kind of token: a short-lived exchange token minted by the identity provider (auth.console) with the audience provider-credentials-service. A login/management token — even a valid one — is rejected: the audience discipline is one JWT, one target service.

The flow

  1. Log in at the identity provider: POST /v1/auth/login. Accounts belonging to several organizations get status: org_selection_required and finish with POST /v1/auth/select-org — the chosen organization becomes the token's org_id.
  2. Exchange the session for a service-scoped token: POST /v1/auth/token/exchange with {"audience": "provider-credentials-service"}. The result is an access-only JWT (ES256, minutes-lived, no refresh) carrying sub (user UUID), org_id, and the raw organization roles.
  3. Call this service with Authorization: Bearer <token>. When the token expires, exchange again — the login session, not this service, is your refresh anchor.
import httpx

auth = httpx.post(f"{AUTH_BASE}/v1/auth/login", json={"email": EMAIL, "password": PASSWORD}).json()
# ... handle org selection / MFA states per the auth service's own docs ...
exchange = httpx.post(
    f"{AUTH_BASE}/v1/auth/token/exchange",
    headers={"Authorization": f"Bearer {auth['access_token']}"},
    json={"audience": "provider-credentials-service"},
).json()
TOKEN = exchange["access_token"]

The identity provider publishes its own developer wiki with the full login state machine; this page covers only what this service needs from it.

What the token must carry

  • iss/aud — the configured issuer and provider-credentials-service; anything else is 401.
  • sub — the user, a canonical UUID (non-canonical forms are rejected).
  • org_id — optional; when present, a canonical UUID. Absent means no organization context: Organization Credentials answers 403, and Credential Status reports null for the org level.
  • roles — the raw organization roles (owner, admin, member, viewer).

How roles map

Two independent mappings read the same roles claim:

  1. Service roles (JWT_ROLE_MAP, default owner→user, admin→user, member→user): produces the §5.1 role that gates endpoints. viewer maps to nothing — such tokens are 401. Elevated roles (provider_admin, auditor) are never derived from org roles by default; granting them is a deliberate deployment decision.
  2. Organization managers (JWT_ORG_MANAGER_ROLES, default owner,admin): checked against the raw roles to gate Organization Credentials — deliberately surviving the flattening above.

So a default deployment reads: every org member is a user; only owners and admins manage the org's credentials.

Dev auth mode

Local development can skip the identity provider entirely: DEV_AUTH_ENABLED=true accepts X-Dev-User-Id, X-Dev-Roles, X-Dev-Org-Id, X-Dev-Org-Roles headers, applying the same UUID and role rules. Requests carrying an Authorization header are always validated as JWTs regardless. Refused in production builds.