JWT standard claims reference
On this page
JWT claims fall into three groups: registered claims (defined by RFC 7519), public claims (registered with IANA but extension), and private claims (custom to your application). This page is the reference for the registered + commonly-used public claims.
For interactive testing, paste a JWT into the decoder — it explains each claim inline.
Registered claims (RFC 7519)
These are the seven core claims defined in the JWT spec. None are required, but if you use them, they have specific meanings.
iss — Issuer
Who created the token. Usually a URL of your auth service.
"iss": "https://auth.example.com"
Validation: the verifier should compare against an allow-list. A JWT from an unexpected issuer is suspicious.
sub — Subject
The principal the token refers to — usually a user ID. Must be unique within the issuer’s namespace.
"sub": "user-12345"
"sub": "auth0|62b1234567890abcdef"
"sub": "google-oauth2|1234567890123456789"
Validation: look up the subject in your user table. If it doesn’t exist or is disabled, reject.
aud — Audience
Who the token is for. A token issued for one service shouldn’t be accepted by another. Can be a string or array of strings.
"aud": "api.example.com"
"aud": ["api.example.com", "internal-rpc"]
Validation: the verifier checks its own identifier is in the
audience. If aud: ["other-service"], reject — the token wasn’t meant
for you.
exp — Expiration time
Token is invalid after this Unix timestamp (seconds since epoch).
"exp": 1735689600
Validation: if now() >= exp, reject. Most libraries do this
automatically. Allow a small clock-skew window (~30s) for distributed
systems.
nbf — Not before
Token is invalid before this Unix timestamp. Used for tokens that become valid in the future (rare).
"nbf": 1735603200
Validation: if now() < nbf, reject.
iat — Issued at
Unix timestamp when the token was created. Informational; doesn’t control validity by itself.
"iat": 1735603200
Use: detect very old tokens, log token age, audit.
jti — JWT ID
Unique identifier for this specific token. Used for replay protection
— a server can keep a list of recently-seen jti values and reject
duplicates.
"jti": "0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b"
A UUID is the natural choice — see UUID v7 on a sister site.
OIDC standard claims
OpenID Connect adds claims for user identity. Common ones:
email and email_verified
"email": "alice@example.com",
"email_verified": true
email_verified is essential — never trust an unverified email for
account-linking or password-reset flows.
name, given_name, family_name, picture
User profile fields. Optional, IdP-dependent.
nonce
"nonce": "n-0S6_WzA2Mj"
Bound to the original auth request. The receiver compares it to the nonce it sent; mismatches mean replay or tampering.
auth_time
"auth_time": 1735603200
When the user actually authenticated (vs when this token was issued). Useful for “force re-auth if older than X” policies.
acr and amr
Authentication context class reference and authentication method(s). For MFA-aware applications:
"acr": "urn:mace:incommon:iap:silver",
"amr": ["pwd", "mfa"]
OAuth scope claim
"scope": "openid profile email read:users write:users"
Space-separated list of granted permissions. Validate per endpoint.
Common custom (private) claims
These aren’t standardized but appear frequently:
| Claim | Convention |
|---|---|
roles | Array of role strings: ["admin", "user"] |
permissions / perms | Array of granular permissions |
tenant / tid | Tenant or organization ID for multi-tenant apps |
org_id | Organization context for the token |
session_id | Reference to a server-side session for revocation |
device_id | Device fingerprint for risk scoring |
Custom claims are fine — but document them. A JWT consumer can’t reliably interpret a private claim without prior agreement.
Validation order
A complete JWT validation does these checks in order:
- Parse — three base64url segments, valid JSON.
- Algorithm —
header.algis in your allow-list (e.g.["HS256"]). Rejectnone. - Signature — verify with the right key for that algorithm.
exp— not expired (with optional skew tolerance).nbf— already valid (with optional skew tolerance).iss— matches expected issuer.aud— your service is in the audience.- Custom claims — roles, scopes, tenant, etc.
- Subject lookup — user still exists and isn’t disabled in your DB.
Any failure rejects the token. Most JWT libraries handle steps 1–7 automatically when you pass the right options; 8–9 are app-specific.
Encoding rules
- Times are Unix seconds (not milliseconds). A common bug: using
Date.now()(ms) directly. - Strings are case-sensitive.
"https://Example.com"≠"https://example.com"forissmatching. - Audience can be string or array. Validators must handle both.
- All claims are optional in the spec. Your validator decides which are required for your application.
Try the tools
- JWT decoder — paste a JWT, see all its claims with explanations
- Verify HMAC — confirm signatures
- Sign HS256 — generate test tokens with custom claims
- What is a JWT? — fundamentals
- JWT vs sessions — when each is right
Related across the network
- epoch.tooljo.com —
iat,exp,nbfare Unix seconds. The converter auto-detects sec vs ms (a common mistake source). - hash.tooljo.com/sha256 — HS256 is HMAC-SHA-256 under the hood. Useful for understanding what the signature actually verifies.
- base64.tooljo.com/url-safe — JWT segments are base64url-encoded. Decode the raw bytes.
- password.tooljo.com — the secret used for HS256 should be at least 32 random characters. Generate one.