JSON Web Tokens (JWT) Attacks
Table of Contents
Introduction #
- In recent weeks, I’ve dedicated a significant amount of time to studying JSON Web Tokens (JWTs).
- JWTs have become a cornerstone of modern web applications, enabling secure communication between parties. However, to truly secure JWTs, it’s crucial to understand their structure, how they work, and where vulnerabilities might arise.
- In this first part of a two-part series, we’ll thoroughly explore the basics of JWTs, setting a strong foundation for more advanced topics in the following part.
What is JWT? #
-
JSON Web Tokens (JWT) are a
compact
,URL-safe
means of representingclaims
to be transferred between two parties. -
The claims in a JWT are encoded as a JSON object that is used as the payload of a
JSON Web Signature (JWS)
structure or as the plaintext of aJSON Web Encryption (JWE)
structure, enabling the claims to be digitally signed or integrity protected with aMessage Authentication Code (MAC)
and/or encrypted. -
JWTs are commonly used for
authorization
andinformation exchange
in modern web applications. -
They allow the server to
verify the authenticity
of the client’s requests without needing to maintain a session on the server, which can be a significant performance benefit.
JWT Structure #
A JWT consists of three parts, separated by dots (.):
- Header
- Payload
- Signature
- These parts are base64 URL-encoded and concatenated to form the JWT token string.
1. The Header #
The header typically consists of two parts: the type of token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.
Example of a JWT header:
{
"alg": "HS256",
"typ": "JWT"
}
This header is then Base64Url encoded to form the first part of the JWT.
2. The Payload #
The payload contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims:
1. Registered claims: #
- These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some examples are iss (issuer), exp (expiration time), sub (subject), and aud (audience).
2. Public claims: #
- These are claims that can be defined by those using JWTs. They must be collision-resistant, meaning that they should be unique across all contexts where they might be used.
3. Private claims: #
- These are the custom claims created to share information between parties that agree to use them and are neither registered nor public.
Example of a JWT payload: #
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
This payload is then Base64Url encoded to form the second part of the JWT.
3. The Signature #
- To create the signature part, you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
For example, if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret)
-
The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed along the way.
-
The final JWT looks something like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- Each part is separated by a dot (.), with the first part being the encoded header, the second part the encoded payload, and the third part the signature.
How JWTs Work #
- JWTs are used for authentication and information exchange. Let’s break down how they typically work in a web application:
User Authentication: #
- When a user logs in, the server validates the credentials and generates a JWT.
- The server sends this JWT to the client (usually in the response).
Token Storage: #
- The client stores the JWT locally, often in local storage or a cookie.
- For each subsequent request, the client sends the JWT in the Authorization header or a cookie.
Token Validation: #
- The server receives the JWT with the incoming request.
- The server validates the JWT by checking its signature and optionally other claims like expiration time.
- If valid, the server processes the request; otherwise, it returns an error.
Stateless Authentication: #
- The server does not need to store session data between requests, as the JWT contains all necessary information.
- This stateless nature is one of the primary benefits of JWTs, reducing the overhead associated with server-side session management.
Common Use Cases for JWT #
1. Authorization #
- One of the most common use cases for JWT is authorization. Once a user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token.
2. Information Exchange #
- JWTs are a good way of securely transmitting information between parties. Since JWTs can be signed, you can be sure that the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn’t been tampered with.
Benefits of Using JWT #
- Compact
- JWTs are compact in size, making them easy to pass in URL parameters, HTTP headers, or in POST requests.
- This compact nature also makes them ideal for mobile devices.
- Self-Contained
- JWTs carry all the necessary information within the token itself, reducing the need for the server to query a database on every request.
- This self-contained nature makes JWTs efficient and scalable for large-scale applications.
- Secure
- When implemented correctly, JWTs are highly secure.
- They allow the use of public/private key pairs for signing (asymmetric cryptography), making them suitable for applications that require strong security guarantees.
Potential Pitfalls and Misconceptions #
- While JWTs offer numerous benefits, they are not without pitfalls. Common misconceptions and potential issues include:
- JWTs are not encrypted: JWTs are simply encoded, not encrypted by default. If sensitive information is included in the payload, it must be encrypted separately.
- Long-lived tokens: JWTs can be stored client-side for extended periods, which can be a security risk if the token is compromised. Always use short expiration times and refresh tokens as needed.
- Incorrect algorithm use: Misconfiguration of the signing algorithm can lead to vulnerabilities, such as accepting tokens signed with the none algorithm.
Conclusion #
-
In this first part of our deep dive into JSON Web Tokens, we’ve covered the fundamental concepts and structure of JWTs.
-
Understanding these basics is crucial before moving on to more advanced topics like JWT vulnerabilities and exploitation techniques, which we’ll explore in the second part of this series.
-
I hope this detailed exploration of JWT basics has provided you with a solid foundation. Stay tuned for the next post, where we’ll take a closer look at the various ways JWTs can be exploited and how to defend against such attacks.