RFC 9068 requires seven claims in a JWT access token: iss, exp, aud, sub, client_id, iat and jti. The header type should be at+jwt. The API must check the type, issuer, audience, signature and expiry, and reject alg none. These rules help stop an ID token from being replayed as an access token.
Why a profile exists
OAuth does not say what an access token looks like. Many servers issue JWTs, but each in its own shape, so API developers wrote custom validation. RFC 9068 standardizes a layout and a validation routine so resource servers can handle tokens from different issuers the same way.
Required claims
| Claim | Meaning |
|---|---|
| iss | Issuer of the token, the authorization server |
| exp | Expiry time |
| aud | The resource server the token is for |
| sub | The subject: the user for user grants, the client or service for machine grants |
| client_id | The OAuth client the token was issued to |
| iat | When it was issued |
| jti | A unique token identifier |
The RFC also describes optional claims for authentication information, identity, and authorization (such as scope, groups, roles and entitlements).
The header
The media type application/at+jwt is registered, and the RFC says the typ header value should be at+jwt (the application/ prefix is recommended to be omitted). Resource servers must verify it and reject anything else.
This matters because an ID token is also a JWT with similar claims. Explicit typing, in line with RFC 8725, helps the resource server tell them apart.
What the API must validate
The RFC lists these checks for resource servers:
- The
typheader isat+jwtorapplication/at+jwt. - If the token is encrypted, decrypt it. If encryption was agreed and the token is not encrypted, the server should reject it.
- The issuer in
issexactly matches the issuer the server expects, usually from discovery. - The
audclaim contains an identifier for this resource server. Otherwise reject. - The signature is valid using the algorithm in
alg, with keys supplied by the authorization server. Rejectnone. - The current time is before
exp, with at most a small leeway for clock skew. - Return the
invalid_tokenerror code for any failure.
If authorization claims are present, the server should combine them with other context to decide whether to allow the call.
Key distribution
The RFC recommends signing JWT access tokens with an asymmetric algorithm, which makes it easy for many APIs to verify without sharing a secret. Authorization servers should publish keys and the expected issuer through authorization server metadata (RFC 8414), or OpenID Connect discovery.
A subtle warning about sub
The RFC warns that clients must not be able to influence sub in ways that confuse resource servers. If a server uses the client ID as the subject for machine tokens, it should stop clients registering an arbitrary client ID, since a malicious client could pick the identifier of a high privilege user.
Test cases to add
Write tests for a token with no typ, one with an ID token type, a wrong issuer, an audience for another API, an expired token, an unsigned token, and a token signed with an unexpected key. Each must be rejected with invalid_token.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how authentication findings on an API are reported, then think about which of the seven checks above would catch each one.
Quick check
Must every API use JWT access tokens?
No. RFC 9068 is a profile for servers that choose JWTs. Opaque tokens with introspection are also valid.
Is checking aud really needed if I trust the issuer?
Yes. The issuer may serve many APIs. The audience check stops a token meant for one API from being accepted by another.
Safeguard's SBOM and dependency scanning shows which JWT validation libraries each API ships and whether any have known advisories. There is a free scan.
Sources
Last reviewed: 19 October 2026.