Registered, public, and private JWT claims
RFC 7519 §4 splits every claim that can appear in a JWT payload into three categories: registered, public, and private. The category doesn't change how a claim is encoded — they're all just JSON members — it defines who governs the name and how likely two systems are to disagree about what it means.
| Category | Defined by | Examples | Collision risk |
|---|---|---|---|
| Registered | RFC 7519 itself | iss, sub, aud, exp, nbf, iat, jti | None — reserved |
| Public | IANA "JSON Web Token Claims" registry | email, name, auth_time, nonce, scope | None if you use registered names as specified |
| Private | Agreement between issuer and consumer | tenant_id, https://example.com/roles | High unless namespaced |
Registered claims
Seven claim names are reserved by the RFC. All are optional, but verifiers should treat the ones they rely on as mandatory:
iss(issuer) — who minted the token; an index into your trusted key set.sub(subject) — who the token is about, unique within the issuer.aud(audience) — who the token is for; the most commonly skipped check in real deployments.exp(expiration) andnbf(not before) — the validity window, in Unix epoch seconds, not milliseconds.iat(issued at) — when it was created.jti(JWT ID) — a unique ID enabling replay detection.
Public claims
A public claim is any claim intended for use across systems. To avoid two products inventing the same name with different meanings, public claim names are supposed to be registered with IANA or use a collision-resistant name (a URI). In practice most public claims you'll meet come from OpenID Connect: email, name, preferred_username, auth_time, nonce, plus the RFC 9068 access-token profile (scope, client_id).
Private claims
Private claims are whatever an issuer and its consumers agree on — tenant_id, plan, roles. Two rules keep them safe:
- Namespace them. Auth0 requires URI-style names like
https://example.com/roles; Microsoft Entra prefixes extension claims withxms_. A bare name likerolerisks silently colliding with a future spec or another vendor. - Never put secrets in them. A signed JWT (JWS) is readable by anyone who holds it — the payload is only base64url-encoded. If a claim value must stay confidential, use JWE encryption instead.
Which claims should you use?
Prefer registered claims for everything they cover, use OIDC names for identity data instead of inventing your own, and keep private claims few and namespaced — every extra claim grows the token that's sent on every request. To see how a real token is categorized, decode it in the TokenPrism debugger: every known claim is annotated from the same reference that powers the complete claims list.