Intermediate

Self-contained and opaque tokens

Compare by-value and by-reference access tokens, their trade-offs, and hybrid patterns such as the phantom token.

An access token can carry its information by value (a self-contained token, usually a signed JWT) or by reference (an opaque random string that points to state held by the authorization server). OAuth deliberately leaves this choice to the deployment.

How each is validated

Self-contained:  API ── verify signature with cached JWKS, check iss/aud/exp ──> decision
Opaque:          API ── POST /introspect (token) ──> Authorization server ──> { active, sub, scope… }

Characteristics

AspectSelf-contained (JWT)Opaque (reference)
ValidationLocal, using public keys.Remote call to introspection.
Latency and AS loadLow; no call per request.Higher; mitigated with caching.
RevocationEffective only at expiry, unless the API checks extra state.Immediate; the AS reports active: false.
Data freshnessSnapshot at issuance.Current at introspection time.
PrivacyPayload readable by the client and anyone who intercepts it.Reveals nothing.
SizeCan be large (claims, signatures).Small, fixed length.
Offline/edge validationPossible.Requires connectivity to the AS.
InteroperabilityStandard format (RFC 9068).Standard introspection (RFC 7662).

When to choose which

Self-contained tokens suit high-volume internal APIs, edge or serverless validation, and environments where a few minutes of revocation delay is acceptable. Keep lifetimes short, for example 5 to 15 minutes.

Opaque tokens suit tokens exposed to third-party clients, scenarios needing immediate revocation, and cases where claims must not be visible to the client.

Hybrid patterns

Phantom token. Clients receive an opaque token. An API gateway introspects it, asking for a JWT, and forwards that JWT to internal services. Outside, tokens reveal nothing and can be revoked; inside, services validate locally.

Client ──opaque──> Gateway ──introspect──> AS
                     │  (receives JWT)
                     └──JWT──> internal APIs (local validation)

Split token. The token is a JWT, but the client receives only part of it (for example, the signature), and the gateway reconstructs the full JWT from a cache. This avoids an introspection call per request.

Signed introspection. RFC 9701 lets the introspection response itself be a signed JWT, useful when the resource server must prove what the AS asserted.

Mitigating the revocation gap of JWTs

  • Short access token lifetimes, with refresh tokens that can be revoked.
  • Sender-constrained tokens (DPoP or mTLS), so a stolen token is not useful.
  • Event-based revocation with Shared Signals for sessions.
  • A deny list keyed by jti or sid for high-risk APIs, accepting the extra lookup.

Common mistakes

  • Clients parsing access tokens and depending on their claims. The format may change; clients should use the ID token or UserInfo for user data.
  • Putting entire permission sets in tokens, producing headers too large for proxies.
  • Caching introspection results longer than the token’s remaining lifetime, or across different audiences.
  • Assuming revoking a refresh token immediately invalidates outstanding JWT access tokens.

References

Knowledge is better when it is shared.Improve this page

Type to search the entire handbook.