~/blog/jwt-claims-reference
> JWT claims reference: iss, sub, aud, exp, nbf, iat explained
· jwt · auth · tokens
A JSON Web Token is three base64url-encoded segments separated by dots: header.payload.signature. The payload is a JSON object, and its keys are claims. RFC 7519 reserves seven short names as "registered claims"; everything else is custom. This is a reference for the standard seven.
iss — issuer
The party that issued the token. Usually the URL of the authorization server: https://auth.example.com. Clients should validate iss matches the expected issuer; otherwise a token minted by a malicious but trusted-to-you server can impersonate a token from the real one.
In OAuth 2 / OIDC, the issuer's discovery document at <iss>/.well-known/openid-configuration tells you where to fetch the signing keys — so trusting iss implicitly trusts the key-discovery path too.
sub — subject
The identifier for the principal the token is about, usually a user ID or service account ID. Scoped to the issuer: a sub of 1234 from auth.example.com is a different principal than sub of 1234 from auth.other.com.
Never use sub as a display name; it is an identifier, not a label. Never put PII in sub unless you own the token's entire lifecycle.
aud — audience
The recipients the token is intended for. Either a string (one audience) or an array (multiple). A resource server MUST reject a token whose aud does not include its own identifier — the audience check is what prevents a token issued for service A from being replayed against service B.
Common bug: using the client ID as audience when you mean the resource server. The audience should be the API's canonical URL or identifier, not the calling app's.
exp — expiration
Seconds since epoch at which the token becomes invalid. Required on any non-trivial token. Tokens with no exp live forever — they are revocable only by key rotation.
Validate with a small clock skew tolerance (commonly 30–60 seconds) to handle the case where the issuer's clock is slightly ahead of the resource server's. Beyond that, refuse.
nbf — not before
Seconds since epoch before which the token is not valid. Rare in practice but useful for pre-issuing tokens that activate later (e.g. a trial that starts at a specific date). Resource servers MUST enforce it or tokens can be replayed before their activation window.
iat — issued at
Seconds since epoch at which the token was issued. Not a validity boundary by itself — iat alone says nothing about whether the token is currently valid. Use it for audit, rate-limit-reset, or re-authentication prompts ("sensitive action: please re-enter your password, this session is older than 30 minutes").
iat in the future is suspicious but not necessarily invalid. Some implementations reject tokens where iat > now + skew.
jti — JWT ID
A unique identifier for the token. Useful for:
- Replay detection (resource server keeps a bloom filter of seen
jtis). - Revocation lists (a specific token ID is marked invalid).
Not required. Only meaningful if the resource server actually tracks it.
The signing + validation flow
A resource server receiving a JWT does, in order:
- Parse the three segments.
- Decode the header, read
algandkid. - Fetch the public key matching
kid(cached from the issuer's JWKS endpoint). - Verify the signature using the algorithm.
- Decode the payload.
- Validate
iss,aud,exp,nbf,iat. - Apply any application-specific checks (scopes, custom claims).
Skipping any step is a vulnerability. In particular, not validating alg is the infamous "alg=none" attack — if your library trusts the header's algorithm claim without whitelisting, an attacker submits alg=none and an empty signature and is trusted.
Decode a JWT and inspect its claims →
Further reading
- How to decode a JWT without verifying it
- RFC 7519 — JSON Web Token
- RFC 7515 — JSON Web Signature