What Is a JSON Web Token (JWT)? RFC 7519 Explained
JSON Web Token (JWT), defined by IETF RFC 7519, is an open industry standard for securely transmitting information between parties as a compact, self-contained JSON object. JWTs are ubiquitous across modern web architecture, serving as authorization tokens in OAuth 2.0, OpenID Connect (OIDC), and microservice API gateways.
Unlike stateful session identifiers stored in centralized Redis or SQL databases, a JWT is completely stateless. All necessary user claims, role permissions, and expiration deadlines are packed directly inside the token. Any application service possessing the cryptographic verification key can validate the token independently without querying a shared database.
Anatomy of a JWT: Header, Payload, and Signature
Every JSON Web Token consists of three distinct strings concatenated by dots (.):
[Header: Base64URL] . [Payload Claims: Base64URL] . [Digital Signature]
1. The Header
The header typically contains two fields: the signing algorithm used (such as HS256 for HMAC with SHA-256, or RS256 for RSA with SHA-256) and the token type (JWT):
2. The Payload (Claims)
The payload contains the claims — statements regarding an entity (typically the authenticated user) and auxiliary metadata. RFC 7519 defines three types of claims:
- Registered Claims: Predefined standard claims that provide consistent interoperability. These include
iss(issuer),exp(expiration time),sub(subject),aud(audience),nbf(not before),iat(issued at), andjti(JWT ID). - Public Claims: Custom claims defined by organization standards, such as Collision-Resistant Namespaces (e.g.
https://example.com/jwt_claims/role). - Private Claims: Custom claims established by mutually agreeing applications (e.g.
userId,tenantId,roles).
3. The Signature
The signature is created by taking the encoded header, the encoded payload, a secret key (or private RSA/ECDSA key), and hashing them using the algorithm specified in the header:
Standard Registered Claims Reference Table
| Claim Key | Claim Name | Data Type | Description & Security Purpose |
|---|---|---|---|
exp |
Expiration Time | NumericDate (Unix Epoch) | Mandatory security claim. Identifies the exact second after which the token must be rejected. |
iat |
Issued At | NumericDate (Unix Epoch) | Records when the token was signed. Useful for calculating token age and revocation thresholds. |
nbf |
Not Before | NumericDate (Unix Epoch) | Identifies the time before which the token must not be accepted by authorization servers. |
sub |
Subject | StringOrURI | Identifies the principal subject of the token (e.g. UUID, email, or database user ID). |
iss |
Issuer | StringOrURI | Identifies the authority that created and issued the token (e.g. https://auth.company.com). |
aud |
Audience | StringOrURI or Array | Identifies the intended recipients or backend APIs that should accept the token. |
jti |
JWT ID | String | Provides a unique identifier for the token. Crucial for token blacklisting and replay prevention. |
JWT Security Best Practices
- Never Store Sensitive Secrets in Claims: Because Base64URL encoding is reversible without a key, never place database passwords, unhashed social security numbers, or private encryption keys in the payload.
- Always Validate the 'alg' Header: Guard against the infamous Algorithm Confusion Attack where attackers modify
"alg": "none"to bypass signature verification entirely. - Store Tokens Securely: Storing JWTs in browser
localStorageexposes them to Cross-Site Scripting (XSS) extraction. Store sensitive authentication tokens in HttpOnly, Secure, SameSite=Strict cookies whenever possible. - Enforce Short Expiration Lifespans: Access tokens should expire in 10 to 15 minutes, paired with secure rotating refresh tokens for extended sessions.