June 13, 2026
JSON Web Tokens (JWT): Structure, Signing, and Claims
What is a JWT?
Rsarith
6 min read
What is a JWT?
JWT stands for JSON Web Token (pronounced "jot"). It is an open standard (RFC 7519) used to securely transmit information between parties as a JSON object. It is widely used in modern web development for user authentication and authorization. A JSON Web Token is a tool that allows users to identify themselves to the server and perform their requests. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Structure of a JWT
A signed JWT is a string made up of three Base64URL- encoded parts separated by dots: header.payload.signature
For example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5ceyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cEach part has a specific role:
- Header: A small JSON object describing the token type and signing algorithm, for example {"alg": "HS256", "typ": "JWT"}.
- Payload: The claims, which is a JSON object containing the actual data (user ID, expiration, custom fields, etc.). The payload is only Base64URL-encoded, not encrypted, so anyone who has the token can read its contents.
- Signature: A cryptographic signature computed over the encoded header and payload using the signing key. The signature is what lets a recipient verify that the token was issued by a trusted party and has not been modified.
Encrypted JWTs (JWE) have a different five-part structure, covered later in this article.
JWTs can be either signed (JWS — JSON Web Signature) or encrypted (JWE — JSON Web Encryption). A signed JWT guarantees the data's integrity and authenticity (proving it was created by a trusted party and hasn't been tampered with), while an encrypted JWT secures the confidentiality of the data (ensuring no one else can read the payload). The two can also be combined in a nested JWT (a JWS that is then wrapped inside a JWE), which is the recommended approach when both integrity and confidentiality are required. Here is how they differ in purpose and structure:
JWS vs. JWE
JWS:
- A signed JWT has 3 parts separated by dots. Contains 3 sections like header.payload.signature
- Header and payload can be Base64-decoded and read.
- Signature verifies that the content has not been changed.
JWE:
- An encrypted JWT has 5 parts separated by dots. Contains 5 sections like header.encryptedKey.iv.ciphertext.authTag
- Payload is encrypted and cannot be read directly.
- Requires a decryption key to access the claims.
Why use JWT?
- Stateless: Unlike traditional session-based systems (which require the server to look up user data in a database for every request), a JWT contains all the necessary user information inside the token itself. This is convenient, but the trade-off is that revoking a JWT before it expires is hard: since the server doesn't track session state, you typically must wait for the token to expire or maintain a separate denylist.
- Scalable: Because it is self-contained, it allows users to remain logged in seamlessly across different servers, microservices, and APIs without repeatedly querying a database.
- Secure: JWTs are signed with a cryptographic key. The signing key can be a public/private key pair (asymmetric, e.g. RSA or ECDSA) or a shared secret (symmetric, e.g. HMAC). When asymmetric signing is used, the issuer's public key is typically distributed via a JWKS (JSON Web Key Set) endpoint or, less commonly, as part of an X.509 certificate.
- Common: JSON parsers are supported by most programming languages.
Signing Algorithms
Signing Algorithm are the cryptographic algorithms used to sign tokens issued for your application or API. A signature is part of a JWT and is used to verify that the sender of the token is who it says it is and to ensure that the message wasn't changed along the way.
- RS256 (RSA Signature with SHA-256): An asymmetric algorithm, which means that there are two keys: one public key and one private key that must be kept secret. The issuer (or Identity Provider) has the private key used to generate the signature, and the consumer of the JWT retrieves a public key from the metadata endpoints provided by issuer and uses it to validate the JWT signature.
- HS256 (HMAC with SHA-256): A symmetric algorithm, which means that there is only one private key that must be kept secret, and it is shared between the two parties. Since the same key is used both to generate the signature and to validate it, care must be taken to ensure that the key is not compromised. This private key (or secret) is created when you register your application (client secret) or API (signing secret) and choose the HS256 signing algorithm.
- PS256 (RSA Signature with SHA-256): An asymmetric algorithm, which means that there are two keys: one public key and one private key that must be kept secret. The issuer (or identity provider) has the private key used to generate the signature, and the consumer of the JWT retrieves a public key from the metadata endpoints provided by issuer and uses it to validate the JWT signature. PS256 uses RSASSA-PSS padding with a random salt, whereas RS256 uses the older PKCS#1v1.5 padding. As a result, signing the same header and payload twice produces different signatures with PS256. PS256 is generally preferred for new applications.
- ES256 (ECDSA with SHA-256): An asymmetric algorithm based on elliptic curve cryptography. Compared to RS256/PS256, ES256 produces much smaller signatures and is faster to verify, making it well suited to mobile clients and high-throughput services. Increasingly recommended for new systems.
- EdDSA (Edwards-curve Digital Signature Algorithm): A modern asymmetric algorithm (typically using the Ed25519 curve) that offers high security, small signatures, and fast verification. Defined for JSON in RFC 8037 and increasingly supported by modern libraries.
JSON Web Token Claims
JSON Web Token Claims are key-value pairs in the payload of a JWT that contain information about a user, device, or entity. JWT claims are grouped into four main categories, all serialized together as a single JSON object:
1. Registered Claims: These are a set of predefined, standard claims that are not mandatory but highly recommended to provide a standardized, interoperable token.
- iss (Issuer): Identifies the principal that issued the JWT.
- sub (Subject): Identifies the principal that is the subject of the JWT (usually the user ID).
- aud (Audience): Identifies the recipients that the JWT is intended for.
- exp (Expiration Time): Identifies the time on or after which the JWT MUST NOT be accepted for processing.
- nbf (Not Before): Identifies the time on or before which the JWT MUST NOT be accepted for processing.
- iat (Issued At): Identifies the time at which the JWT was issued.
- jti (JWT ID): Provides a unique identifier for the JWT.
2. Public Claims: These are claims defined by those who use JWTs to prevent collisions. They should either be defined in the IANA JSON Web Token Claims registry or be defined as a URI that contains a collision-resistant namespace.
3. Private Claims: These are custom claims created to share information between parties that agree on using them. They are not registered or public claims and carry a risk of collision if the keys are not managed properly between the communicating parties.
4. Custom/Namespaced Claims: In modern applications (such as OAuth 2.0 or OpenID Connect), these are custom user attributes (like roles, permissions, or email). To prevent naming conflicts with standard registered claims, identity providers usually recommend placing custom claims inside a unique namespace (e.g., https://my-app.com).
Limitations and Pitfalls
JWTs are powerful, but they come with real trade-offs that are easy to overlook:
- Revocation is hard. Because JWTs are stateless, you cannot easily invalidate a token before it expires. The common mitigations are short access-token lifetime (a few minutes), pairing access tokens with longer-lived refresh tokens, or maintaining a server-side denylist for emergency revocation.
- Payloads are not secret. A signed JWT only protects integrity, not confidentiality. The payload is Base64URL -encoded, not encrypted, so anyone who gets the token can read its contents. Never put passwords, secrets, or other highly sensitive data in a JWS payload. Use a JWE (or a nested JWS-then-JWE) if you need confidentiality.
- The "alg: none" attack. The JWT spec historically allowed an "alg": "none" header, meaning the token is unsigned. Some libraries accepted such tokens as valid, allowing attackers to forge any payload they wanted. Always pin the expected signing algorithm in your verification code; never trust the "alg" value blindly from the header.
- Token size. Because JWTs carry their claims with them on every request, large payloads add up quickly, especially when sent in HTTP headers. Keep claims minimal.
- Client-side storage. Storing JWTs in browser localStorage exposes them to XSS attacks. Prefer HTTP-only, secure cookies for browser clients, or in-memory storage that is refreshed on each session.
RFC 8725 (JSON Web Token Best Current Practices) consolidates these and other recommendations and is worth reading before deploying JWT-based auth in production.
References
By jwt.io, Introduction to JSON Web Tokens, https://www.jwt.io/introduction#what-is-json-web-token-structure
By Melih Firat, What is JWT? https://medium.com/@firatmelih/what-is-jwt-8f570fa2470e
By auth0.com, JSON Web Tokens, https://auth0.com/docs/secure/tokens/json-web-tokens
Jones, M., Bradley, J., & Sakimura, N. JSON Web Token (JWT). RFC 7519, IETF, May 2015. https://www.rfc-editor.org/rfc/rfc7519
Jones, M., Bradley, J., & Sakimura, N. JSON Web Signature (JWS). RFC 7515, IETF, May 2015. https://www.rfc-editor.org/rfc/rfc7515
Jones, M., & Hildebrand, J. JSON Web Encryption (JWE). RFC 7516, IETF, May 2015. https://www.rfc-editor.org/rfc/rfc7516
Sheffer, Y., Hardt, D., & Jones, M. JSON Web Token Best Current Practices. RFC 8725, IETF, February 2020. https://www.rfc-editor.org/rfc/rfc8725