Building JWT claims
Which claims should the tokens you issue contain? It depends on who verifies them and what they authorize. Here is a practical guide for issuers — no claim is mandatory for every JWT.
The registered claims
| Claim | Set it to | Why |
|---|---|---|
| iss | Your issuer URL, identical on every token | Lets verifiers reject tokens from other issuers |
| sub | A stable, unique, non-reassignable ID | Identifies the user or service; avoid emails |
| aud | The API(s) that should accept the token | Prevents a token for one service being replayed at another |
| exp | Now + a short lifetime | Limits the damage of a leaked token |
| nbf | Usually now, or omit | Delays validity for scheduled access |
| iat | Now | Useful for auditing and max-age checks |
| jti | A random UUID | Enables replay detection and revocation lists |
Claims by token type
API access token (RFC 9068 style)
{ "iss": "https://auth.example.com/", "sub": "user-8127", "aud": "api.example.com",
"client_id": "web-app", "scope": "read:orders write:orders",
"iat": 1790602800, "exp": 1790603700, "jti": "7c0f…" }Service-to-service token
{ "iss": "billing-service", "sub": "billing-service", "aud": "ledger-service",
"iat": 1790602800, "exp": 1790603100 }One-time action token (email verification)
{ "sub": "user-8127", "aud": "email-verification", "email": "sam@example.com",
"jti": "a4e3…", "iat": 1790602800, "exp": 1790689200 }These are examples, not universal security recommendations. Follow the profile your verifier or identity provider documents.
Designing custom claims
- Keep them small — the token travels with every request.
- Namespace them to avoid collisions (
https://example.com/rolesorex_roles). - Use JSON types deliberately: arrays for lists, booleans for flags, strings for large numeric IDs.
- Remember they are readable: no secrets, no sensitive personal data.
- Prefer stable facts (roles, tenant) over volatile ones (balance, profile fields) that go stale before exp.
Add standard and custom claims with typed values — string, number, boolean, array, object or null — and switch to raw JSON at any time.
Open the claims builderValidate claims after issuing with negative test tokens.