Token lifetimes and scopes are the main levers for limiting damage when something leaks.
An access token is presented to the API in the Authorization: Bearer <token> header. It is a bearer token: whoever holds it can use it, like cash. Hence:
- Keep access tokens short-lived (minutes to an hour;
expires_intells you). - Send them only over TLS, never in URLs.
- Request the minimum scopes (
orders.read, notadmin). Scopes are strings defined by the API; the AS may grant fewer than requested, and the token response'sscopefield says what you got.
Access tokens come in two formats. JWT access tokens (profile in RFC 9068) can be validated by the API locally. Opaque tokens are random strings that the API checks with the AS through introspection (RFC 7662). Clients should treat both as opaque and never parse them: the format is a contract between AS and API.
A refresh token is a long-lived credential sent only to the AS's token endpoint (grant_type=refresh_token) to obtain a new access token. It lets apps keep working without re-prompting the user, while API-facing tokens stay short-lived.
Refresh tokens are high-value: store them server-side or in secure OS storage, and expect the AS to rotate them on each use. The offline_access scope (in OIDC) asks for one explicitly.
Example
# Call an API with a bearer access token
curl -s https://api.example.com/orders \
-H "Authorization: Bearer $ACCESS_TOKEN"
# 401 + WWW-Authenticate: Bearer error="invalid_token" when it has expired
# Refresh it (confidential client authenticates with its secret)
curl -s https://auth.example.com/token \
-u "web-app:$CLIENT_SECRET" \
-d grant_type=refresh_token \
-d refresh_token="$REFRESH_TOKEN"
# {"access_token":"<new>","token_type":"Bearer","expires_in":900,
# "refresh_token":"<rotated>","scope":"orders.read"}Remember
- Bearer tokens work for whoever holds them: short lifetimes, TLS only
- Request the minimum scopes; check the granted
scope - Clients treat access tokens as opaque
- Refresh tokens go only to the token endpoint
Watch out for
- Putting access tokens in query strings, where they end up in logs and Referer headers.