Tokens: JWT vs. Opaque
Access-, Refresh- und ID-Tokens; die JWT-vs-Opaque-Abwägung; JWK-Schlüsselrotation; und das Anpassen von Claims, damit Resource Server ihnen vertrauen können.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
The flows exist to deliver tokens. Now the tokens themselves: there are three kinds with different jobs, two formats with a real trade-off, and a key-management story that decides whether resource servers can trust what you issue. Get this layer right and BookVault's API can validate your tokens with zero calls back to the auth server - or deliberately choose the opposite.
Three tokens, three jobs
- Access token - the credential the client presents to the resource server on every API call. Short- lived (minutes). Answers "may this request proceed?"
- Refresh token - a longer-lived credential the client exchanges for a new access token when the old one expires, without re-prompting the user. Held only by the client, sent only to the auth server.
- ID token (OIDC) - a JWT for the client asserting who logged in. Never sent to the resource server.
Short access tokens + refresh tokens is the standard trade-off: exposure is limited (a leaked access token dies in minutes) while the user isn't forced to log in constantly (the refresh token quietly renews it).
JWT vs. opaque
The access token can take one of two formats, and this is the module's central decision:
JWT (self-contained) - a signed JSON payload the resource server validates locally by checking the signature. All the claims (subject, scopes, expiry) are inside the token:
Header.Payload.Signature → {"sub":"member-42","scope":"catalog:read","exp":...}- Pro: no network call to validate - fast, scales, no auth-server dependency on the hot path.
- Con: can't be instantly revoked (it's valid until it expires), and claims can go stale.
Opaque (reference) - a random string that means nothing on its own. The resource server calls the auth server's introspection endpoint to ask "is this valid, and what are its claims?"
- Pro: instantly revocable - the auth server just stops recognizing it.
- Con: a network call per request (mitigated with caching) and a hard dependency on the auth server.
The common pattern: JWTs for scale, with short lifetimes to bound the revocation gap; opaque tokens when instant revocation matters more than latency.
Keys: how a resource server trusts a JWT
A JWT is only as trustworthy as its signature. Sign with asymmetric keys (RS256/EC), not the HS256 shared secret BookVault started with:
- The auth server signs with a private key.
- It publishes the matching public keys at
/oauth2/jwks(a JWK Set). - The resource server fetches those public keys (once, then cached) and verifies signatures locally - it
never needs the private key, and key rotation is automatic via the
kidheader.
That's the upgrade over HS256: with a shared symmetric secret, every resource server that can verify a token can also forge one. With asymmetric keys, resource servers can only verify - forging requires the private key that never leaves the auth server.
Customize claims at issue time
Resource servers authorize on token claims, so put what they need in the token. Spring Authorization Server lets
you add claims with an OAuth2TokenCustomizer - e.g. stamp a roles or tenant claim so BookVault can do
@PreAuthorize checks without a database lookup. Keep it minimal, though: tokens travel on every request, and
fat tokens are slow and leak more if stolen.
A JWT is a tamper-proof festival wristband: printed on it is your access level and expiry, sealed with a hologram (signature) anyone at any gate can verify on sight without radioing the box office - fast, but once it's on your wrist they can't un-issue it until it expires. An opaque token is a numbered locker chit: the number means nothing until staff look it up in their ledger (introspection), which lets them void it instantly but requires a lookup every time. The hologram is asymmetric signing - gates can check it but can't forge it, because only the box office has the stamp.
BookVault is going multi-service: an API gateway and three backend services, all validating tokens on every request, at high volume. But the security team requires that a compromised member account can be locked out immediately. JWT or opaque? Is there a way to get most of both?
What is the main trade-off between JWT (self-contained) and opaque (reference) access tokens?
Key takeaways
- Three tokens: access (to the resource server, short-lived), refresh (renew without re-login), ID token (identity, for the client only).
- JWTs are self-contained and validated locally with no network call, but can't be instantly revoked; opaque tokens are introspected per request and are instantly revocable.
- The common pattern is short-lived JWTs (bounding the revocation gap) plus refresh tokens, choosing opaque only when instant revocation dominates.
- Sign with asymmetric keys (RS256/EC): the auth server holds the private key and publishes public keys at /oauth2/jwks so resource servers can verify but not forge.
- Customize token claims at issue time (OAuth2TokenCustomizer) so resource servers authorize without extra lookups - but keep tokens lean.