← BlogMarch 5, 2026 · 8 min
JWT Registered Claims Explained
iss, sub, aud, exp, nbf, iat, jti — the seven registered claims from RFC 7519 explained with real examples of how and when to use each one.
Where these come from
RFC 7519 defines a small set of **registered claim names** for the JWT payload. None of them are mandatory, but they're standardized specifically so different systems can interoperate without inventing their own conventions for the same concepts. You're free to add custom claims alongside them.
`iss` — Issuer
Identifies who issued the token, usually a URL or a stable string like `https://auth.example.com`. A resource server should validate this matches an expected, trusted issuer — otherwise a token from an unrelated system could be replayed against your API if it happens to share a signing key or algorithm.
`sub` — Subject
The principal the token is about — almost always a stable, unique user or service identifier, not an email address (emails can change). This is the claim you should use as your "who is this" lookup key.
`aud` — Audience
Identifies the intended recipient(s) of the token — typically an API identifier or client ID. A resource server should reject any token whose `aud` doesn't include it. This is the claim most often skipped, and skipping it is what allows a token minted for one API to be replayed against a different one.
`exp` — Expiration Time
A Unix timestamp after which the token must not be accepted. Every JWT should have one — see our dedicated post on expiration and clock skew for the details.
`nbf` — Not Before
The token must not be accepted before this time. Useful for pre-issuing tokens that shouldn't activate immediately, but rare in everyday auth.
`iat` — Issued At
When the token was created. Useful for computing token age, auditing, and as an input to some revocation strategies (e.g., "reject any token issued before the user's last password change").
`jti` — JWT ID
A unique identifier for this specific token, typically a UUID. This is what makes token-level revocation possible — you can maintain a denylist of `jti` values for tokens that must be rejected before their natural expiration, without needing to blocklist by user.
Putting them together
A well-formed access token payload might look like:
- `iss`: `https://auth.example.com`
- `sub`: `user_8f2a1`
- `aud`: `https://api.example.com`
- `iat`: 1750000000
- `exp`: 1750000900
- `jti`: `5c1f5e2e-8b7a-4b3e-9b7e-2f6a1e9c9b4a`
Custom claims
Anything not in the registered set is a **public** or **private** claim. Public claims should be namespaced (e.g., a URI) to avoid collisions if you expect other systems to consume the token; private claims are just agreed upon between the parties involved, like `role` or `plan`. Avoid stuffing large or sensitive data into custom claims — the payload is base64url-encoded, not encrypted, and readable by anyone with the token.
Checklist
- Always set `iss`, `sub`, `aud`, `iat`, and `exp` on every token you issue.
- Validate `iss` and `aud` on every verification, not just the signature.
- Use `jti` if you need fine-grained, per-token revocation.
- Use `sub` as your stable identity key, never something mutable like an email.
- Namespace custom claims to avoid future collisions with registered or third-party claims.
Related tools and reading