JSON Web Tokens (JWTs) have become the de facto standard for stateless authentication and authorization in modern web architecture. But what exactly is inside a JWT? The power of a JWT lies in its payload, which is composed of JSON key-value pairs known as claims. A JWT claim is simply a piece of information asserted about a subject—typically a user—by an issuer.
Whether you are debugging an authentication flow, building a microservices architecture, or auditing your security posture, understanding JWT claims explained in depth is non-negotiable. If you need to quickly view the claims inside your current token without sending your sensitive data to a third-party server, you can use our JWT Debugger. Because ZeroData's moat is "no uploads, local processing, browser-only," our tool decodes your JWT entirely locally in your browser. This privacy-first approach ensures your sensitive tokens never leave your machine.
In this comprehensive guide, we will break down the standard registered JWT claims (such as iss, aud, exp, nbf, iat, and jti), explore the nuances of custom JWT claims security, and explain how to properly validate these claims to prevent severe vulnerabilities.
iss (Issuer), exp (Expiration Time), sub (Subject), and aud (Audience). Remember: JWTs are Base64Url encoded, not encrypted. Never store sensitive PII in your custom claims!
What Are JWT Claims? (Base64 vs. Encryption)
Before diving into specific claims, we must clarify a fundamental misconception: JWTs are not encrypted by default. A standard JWT (technically a JWS, JSON Web Signature) consists of three parts: a header, a payload, and a signature. The payload contains the claims.
The payload is merely Base64Url encoded. This means that anyone who intercepts the token can instantly decode it and read all the claims inside. The signature ensures that the claims have not been tampered with, but it does not hide the data. Therefore, JWT claims should be used to transmit necessary routing and authorization data—like user IDs or roles—but never passwords, social security numbers, or internal system secrets.
Because these tokens are readable by anyone holding them, using a secure, local tool like our JWT Debugger is critical for development. You can paste your token, decode it instantly, and see the exact JSON structure of your claims without risking exposure over the network.
The 7 Standard Registered JWT Claims
The IETF RFC 7519 specification defines a set of standard, or "registered," claims. While these are not mandatory, they provide a standardized way for different systems to share common information. Let's break down each standard JWT claim.
1. iss (Issuer)
The iss claim identifies the principal that issued the JWT. In most applications, this is the authorization server (e.g., Auth0, Keycloak, or your custom identity provider). When an API receives a token, it checks the iss claim to ensure it trusts the authority that minted the token.
{
"iss": "https://auth.zerodatatools.com/"
} 2. sub (Subject)
The sub claim identifies the principal that is the subject of the JWT. Typically, this is the unique identifier for the user (like a database UUID). The subject must be unique within the context of the issuer.
{
"sub": "user_98a7b6c5d4e3f2"
} 3. aud (Audience)
The aud claim identifies the intended recipients of the JWT. An audience can be a specific API, a microservice, or a generic resource server. If your API is https://api.myapp.com, and it receives a token where the aud claim is https://billing.myapp.com, it must reject the token. This prevents a token issued for one service from being maliciously used against another.
{
"aud": ["https://api.zerodatatools.com", "https://analytics.zerodatatools.com"]
} 4. exp (Expiration Time)
The exp claim identifies the expiration time on or after which the JWT must not be accepted for processing. It is represented as a NumericDate (seconds since the Unix epoch). A JWT should always have an expiration time to limit the window of opportunity if the token is compromised.
If you are encountering issues with tokens expiring prematurely or want to convert these Unix timestamps into human-readable formats, you can use our JWT Expiry Checker.
{
"exp": 1716307200
} 5. nbf (Not Before)
The nbf claim is the exact opposite of exp. It identifies the time before which the JWT must not be accepted. This is useful for issuing tokens that are only valid starting at a future date, such as for a scheduled job or a future access grant.
{
"nbf": 1716220800
} 6. iat (Issued At)
The iat claim identifies the time at which the JWT was issued. This can be used to determine the age of the JWT. Some systems use the iat claim in conjunction with password reset events: if a token was issued before the user's password was changed, the token can be invalidated.
{
"iat": 1716220800
} 7. jti (JWT ID)
The jti claim provides a unique identifier for the JWT. This is crucial for preventing replay attacks and for implementing token revocation. If a user logs out, the server can place the jti of their token on a blocklist (or revocation list) until the token's exp time is reached.
{
"jti": "8b92d6e3-1c4f-4d9a-a8b2-5f6e7d8c9b0a"
} Public vs. Private Custom Claims
Beyond the standard registered claims, developers can add their own claims to the payload. These fall into two categories: public claims and private claims.
Public Claims
Public claims are custom claims that are registered with the IANA JSON Web Token Claims Registry or are defined as collision-resistant URIs. They are meant to be shared across organizations without fear of naming collisions. For example, if you want to include a "role" claim, you might namespace it to avoid conflicting with another system's definition of a role.
{
"https://zerodatatools.com/claims/role": "admin"
} Private Claims
Private claims are custom claims created to share information specifically between parties that agree on using them (like a specific client and your backend server). They are not registered and are subject to collision, but are perfectly fine for internal application use.
{
"tenant_id": "tnt_12345",
"is_pro_tier": true
} Custom JWT Claims Security Best Practices
When designing your JWT payload, custom JWT claims security must be a top priority. Because JWTs are sent with every HTTP request, their size and contents drastically impact both performance and security. For an exhaustive look at securing your tokens, read our Complete Guide to JWT Security.
1. Never Store PII
As mentioned earlier, JWTs are Base64 encoded, not encrypted. Do not store Personally Identifiable Information (PII) such as email addresses, physical addresses, or financial data in a JWT. If a token is stored in a browser's LocalStorage and is stolen via an XSS attack, all that PII is immediately exposed. Only store non-sensitive identifiers (like a database UUID) and let the backend look up the sensitive data securely.
2. Keep the Payload Small
Every claim you add increases the size of the JWT. Since the token is typically sent in the Authorization header of every single HTTP request, a bloated JWT can severely degrade network performance and even exceed HTTP header size limits (which commonly cap around 8KB). Only include claims that are strictly necessary for routing and immediate authorization.
3. Validate Claims Rigorously
It is not enough to verify the token's cryptographic signature; you must also validate the claims. A common security failure is trusting the exp claim but forgetting to check the aud or iss claim. If your system accepts tokens from multiple issuers, failing to validate the iss claim could allow a token meant for a staging environment to authenticate a user in production.
Common JWT Validation Errors
When working with JWT libraries across different languages (like Node.js, Python, or Go), you will frequently encounter validation errors if claims are not managed correctly. Here are the most common ones:
- TokenExpiredError: The current time is after the time specified in the
expclaim. The token is dead and the user must re-authenticate (or use a refresh token). - JsonWebTokenError (Invalid Audience): The
audclaim in the token does not match the expected audience string provided to the verification function. - NotBeforeError: The current time is before the time specified in the
nbfclaim. The token is not yet active. - Invalid Issuer: The
issclaim does not match the expected identity provider.
By understanding exactly how standard JWT claims operate, you can architect more secure, robust authentication systems. Always remember to validate your claims, keep your payloads light, and use privacy-first tools like ZeroData to inspect your tokens locally.