JWT Claims Explained: exp, iat, nbf, iss, aud and sub

Reviewed September 3, 2026 · Maintained by William

JWT claims are just fields in a JSON object until a trusted verifier applies rules to them. The registered names below are common because they let systems express identity, issuer, audience and time boundaries in a consistent form.

exp — expiration time

exp is a NumericDate after which the token should not be accepted. It is normally expressed as seconds since the Unix epoch.

{ "exp": 1788441600 }

A client-side expiry checker can tell you how that number compares with the current clock. It cannot prove the token is authentic or that the server will accept it.

iat — issued at

iat records when the token was issued. It is useful for logging, age limits and investigating surprising sessions. Do not automatically reject a token just because iat is absent unless your application requires it.

nbf — not before

nbf says the token should not be accepted before a particular time. Small differences between machine clocks are normal, so libraries often support a deliberately limited clock-skew allowance.

iss — issuer

iss identifies the principal that issued the JWT. Verification should compare it with an expected issuer value; simply displaying it is not enough.

aud — audience

aud identifies the intended recipient or recipients. An API that accepts tokens from multiple clients should still verify that its own audience is represented. A valid signature for the wrong audience can still be the wrong token for your service.

sub — subject

sub identifies the subject the claims describe. It might be a user ID, service ID or another application-specific identifier. Treat its meaning as part of the issuer’s contract rather than assuming it is an email address or username.

Worked example

{
  "iss": "https://auth.example.com",
  "sub": "user_1024",
  "aud": "inventory-api",
  "iat": 1788434400,
  "nbf": 1788434400,
  "exp": 1788438000
}

Reading this payload can help a developer understand why a request might be considered early or expired. Trust still requires signature verification plus expected issuer/audience rules.

Common mistakes

  • Comparing milliseconds from JavaScript Date.now() directly with JWT seconds.
  • Checking only exp and ignoring issuer/audience.
  • Assuming a future expiration proves the token is valid.
  • Granting authorization directly from unverified claims.

Primary reference

RFC 7519 §4.1 — Registered Claim Names

Read claims as a set, not isolated fields

JWT bugs often come from validating one familiar claim and assuming the rest of the token is acceptable. A production verifier should interpret claims in the context of the application. For example, a future exp does not help if iss belongs to a different identity provider or aud names another API.

Worked time-claim example

{
  "iat": 1788433200,
  "nbf": 1788433200,
  "exp": 1788436800
}

The intended window is one hour. A verifier should compare these NumericDate values with a trustworthy server clock and apply only a small, deliberate clock-skew allowance. It should not silently extend the token by hours merely to hide clock problems. If the token is rejected near a boundary, inspect NTP/time synchronization and the identity provider’s issuance policy.

Issuer and audience example

Suppose an API expects iss=https://login.example.com/ and aud=inventory-api. A correctly signed token with aud=billing-api should still be rejected by the inventory service. Signature verification tells you who signed the token; audience validation tells you whether the signer intended this token for this recipient.

Claims that need application-specific policy

sub is commonly used as a stable subject identifier, but applications should avoid assuming it is an email address or database primary key unless the issuer contract says so. Custom claims such as role, scope or permissions are even more application-specific. Document whether they are strings, arrays, space-delimited scopes or namespaced values and reject unexpected shapes.

Debugging checklist

  • Convert NumericDate values to UTC first; then compare with server time.
  • Confirm whether aud is a string or array and whether your library handles both correctly.
  • Compare issuer values exactly; trailing slashes and environment-specific issuer URLs can matter.
  • Do not treat a missing optional claim as equivalent to an expected value. Decide explicitly which claims your application requires.
  • When troubleshooting, use a redacted or non-production token. Claims can reveal user identifiers and bearer tokens can grant access.

What the browser tools can and cannot tell you

The JWT Claims Decoder can make timestamps and claim names easier to inspect, while the JWT Expiry Checker focuses on time-related claims. Neither tool receives your verification key, so neither can establish authenticity. The correct next step after inspection is to fix or test the server-side verifier, not to use the decoded payload as an authorization source.

About the review

This guide is maintained by William. Technical claims are checked against primary or authoritative references where applicable. See How We Test CodeNimbleTools for the site-wide review and correction process.