Protocols and how-tos
How to validate a JWT access token in your API
The checks an API must run on a JWT access token — signature, algorithm, issuer, audience, expiry, type — and when introspection is the better choice.
The short answer
An API receiving a JWT access token must verify the signature with a key from the issuer's JWKS using an algorithm it expects, then check iss, aud, exp (and nbf if present), and the token type, before reading scopes or the subject. RFC 9068 defines the JWT access token profile, including the at+jwt type that stops an ID token being accepted as an access token.
Sources last reviewed .
The checks, in order
- Reject the token unless the header's typ is at+jwt (or application/at+jwt) when your issuer follows RFC 9068. This prevents ID tokens and other JWTs from the same issuer being replayed as access tokens.
- Select the verification key by kid from the issuer's JWKS, fetched over TLS and cached. Refresh the cache on an unknown kid, rate-limited.
- Verify the signature with the algorithm you expect for that key. Never accept alg=none and never let the header switch between symmetric and asymmetric algorithms (RFC 8725 section 3.1).
- Check iss equals the expected issuer exactly, and aud contains your API's identifier.
- Check exp and nbf with a small clock-skew allowance.
- Only now read sub, client_id and scope, and make your authorization decision.
- If the token is DPoP-bound (cnf.jkt), require and verify a matching DPoP proof.
JWT or introspection?
A self-contained JWT can be validated locally with no network call, but it stays valid until it expires even if the session behind it has been revoked. Token introspection (RFC 7662) asks the authorization server on each request (or with a short cache) and reflects revocation immediately. Short JWT lifetimes plus introspection for sensitive operations is a common compromise.
Common mistakes
- Decoding the payload and trusting it without verifying the signature.
- Accepting any audience because 'it is our own issuer'.
- Treating scope as the whole authorization model; scopes are coarse, and object-level checks still belong in your API (OWASP API Security Top 10, API1: Broken Object Level Authorization).
Keep reading
Building on any of this?
Tell us what you're putting together. We'll tell you plainly whether Authreads fits it.