Tokens

A successful authentication produces JSON Web Tokens. Each type has one job in the OAuth2 and OIDC protocol.

Token types

TokenPurposeDefault lifetime
Access tokenAuthorize API requests against a resource server300s
Refresh tokenGet new access tokens without asking the user again86400s
ID tokenCarry the user’s identity to the client, per OIDC300s
Temporary tokenAuthorize the completion of required actions, nothing else300s

JWT structure

Every token is a signed JWT: header, payload, signature.

Standard claims

ClaimDescription
subSubject, the user’s id
audAudience, a list of client ids
azpAuthorized party, the client that requested the token
issIssuer, the realm URL
typToken type
expExpiration timestamp
iatIssued-at timestamp
jtiUnique token identifier
scopeSpace-separated list of granted scopes
sidOIDC session id, the user session this token was issued against

sid is absent for flows that establish no SSO session, client_credentials among them. Treat a missing sid as “not session-bound”, not as an invalid token.

Identity and mapper claims

preferred_username and email are written directly when the matching scope is granted. Everything else comes from protocol mappers configured on client scopes, and is flattened into the payload:

ClaimSource
preferred_usernameprofile scope
given_name, family_nameprofile scope
email, email_verifiedemail scope
realm_access.rolesroles scope, through oidc-usermodel-realm-role-mapper

Because mappers are configurable, the exact claim set depends on the scopes assigned to the client.

Token lifetimes

Lifetimes come from two places:

  1. Realm defaults, which apply to every client in the realm.
  2. Client overrides, which win when they are set.
TokenRealm defaultClient override
Access tokenaccess_token_lifetime_secs (300s)access_token_lifetime
Refresh tokenrefresh_token_lifetime_secs (86400s)refresh_token_lifetime
ID tokenid_token_lifetime_secs (300s)id_token_lifetime
Temporary tokentemporary_token_lifetime_secs (300s)temporary_token_lifetime

The rule: if the client sets an override, use it, otherwise fall back to the realm.

Token generation chain

graph LR
    A[User + Client] --> B[Resolve Scopes]
    B --> C[Execute Protocol Mappers]
    C --> D[Build JWT Payload]
    D --> E[Sign with Realm Key]
    E --> F[Access Token + Refresh Token + ID Token]
  1. The user authenticates to a client
  2. Default scopes (plus any requested optional scopes) are resolved
  3. Protocol mappers from each scope produce claims
  4. Claims are assembled into the JWT payload with standard claims
  5. The token is signed using the realm’s signing key and algorithm
  6. Access, refresh, and (optionally) ID tokens are returned

Token introspection

A resource server validates a token by calling the introspection endpoint:

curl -X POST http://localhost:3333/realms/{realm}/protocol/openid-connect/token/introspect \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=eyJhbG..." \
  -d "client_id=my-client" \
  -d "client_secret=my-secret"

The response carries active: true or active: false, plus the full claim set when the token is still live.