Tokens & claims
A successful authorization-code exchange returns up to three tokens: an ID
token (who the user is), an access token (authorization to call APIs), and
— when you request offline_access — a refresh token.
ID token
The ID token is an RS256-signed JWT proving the user's identity to your app. Validate it, then read its claims.
Protocol claims: iss, sub, aud, exp, iat, auth_time, nonce.
Identity claims (present according to the scopes granted):
| Claim | Scope | Meaning |
|---|---|---|
name | profile | Display name |
email | email | Email address |
email_verified | email | Whether the email is verified |
phone_number | phone | Phone in E.164 form |
phone_number_verified | phone | Whether the phone is verified |
sub is the stable, unique user identifier — use it as your foreign key, not
the email (emails can change). Subject type is public, so sub is consistent
across all clients in the environment.
Access token
The access token is also an RS256 JWT, valid for 15 minutes. Present it as a bearer token to resource servers you protect. Resource servers should validate it exactly like the ID token (signature, issuer, audience, expiry) before trusting its claims.
Refresh token
Requested via the offline_access scope, the refresh token lets you obtain new
access tokens without sending the user back through login. It is valid for 30
days and rotates on every use: each refresh returns a new refresh token and
invalidates the one you sent. Store only the latest one.
Important: Never reuse an old refresh token. Replaying a rotated token is treated as a compromise signal — NamoID revokes the entire refresh chain and writes a
security.refresh_replayaudit event. Always persist the newest refresh token returned by each exchange.
Validating tokens
Any conformant JWT/OIDC library does this for you. The manual checklist:
- Fetch the signing keys from the
jwks_uriin the discovery document. - Select the key by the token header's
kid. - Verify the RS256 signature.
- Check
issequals your issuer URL exactly. - Check
audcontains yourclient_id. - Check
exp/iatwith ≤ 30 seconds of allowed clock skew. - For the ID token, check
noncematches the one you sent.
Because keys rotate with overlapping windows, always resolve the key by kid
from the live JWKS rather than caching a single key indefinitely. A short cache
with kid-miss refresh is the right pattern.
Revocation
Tokens can be revoked at the revocation endpoint, and refresh chains are revoked automatically on replay or when a session is ended. See Sessions and the OIDC endpoints reference.