See for yourself – run a scan on your code right now

Introduction

The world of application development is a balance between providing features and ensuring security. One tool that stands as a bridge between functionality and security is the JSON Web Token (JWT). While powerful and versatile, like all tools, it requires understanding and caution in its implementation.

A Primer on JWTs

JWT is a concise, URL-safe method of representing claims between two parties. It’s become the darling of modern application development, finding its niche in tasks like Single Sign-On (SSO) and API security.

Structure Matters: The three-fold structure of a JWT — Header, Payload, and Signature — is its strength and its Achilles heel. The Header details the token type and algorithm used. In essence, the Payload (or claim) is the core data the sender wants to communicate to a receiver, and the Signature authenticates the source and ensures data hasn’t been altered.

 

// Typical JWT structure
const jwt = {
    header: {
        alg: “HS256”,
        typ: “JWT”
    },
    payload: {
        sub: “1234567890”,
        name: “John Doe”,
        iat: 1516239022
    },
    signature: “fjdlfj93D2… (hashed combination of header and payload)”
};

Dissecting a JWT, like the example above, clarifies its components and the data it carries.

Common Security Risks Associated with JWTs

  • Interception: With increasing numbers of Man-in-the-Middle (MitM) attacks, unencrypted JWTs pose a risk.
  • Algorithms and Keys: JWT’s flexibility in allowing different algorithms is a boon, but weak algorithms or keys lead to vulnerabilities.
  • Token Storage: How and where you store JWTs can introduce vulnerabilities. The omnipresent localStorage is often a tempting but dangerous choice.

 

// Risky JWT practice
const token = jwt.sign({ user: ‘Alice’ }, ‘simpleKey’);
localStorage.setItem(‘userToken’, token);

This code shows a token that’s easily retrievable through browser tools. Any malicious script can siphon off tokens stored this way.

Best Practices to Safeguard JWTs

The Secure Transmission Protocol: HTTPS isn’t just for login pages or e-commerce sites. Any data transmitted between client and server, especially JWTs, should use HTTPS.

Strength in Algorithms: The security of JWTs heavily relies on the strength of the cryptographic algorithms used to sign them. For instance, the RS256 algorithm, a member of the RSA family, is known for its robust protection. It offers a level of security that’s substantially higher than some of its counterparts, like HS256.

To provide context, when generating a JWT token, choosing the right algorithm becomes crucial:

const strongToken = jwt.sign({ user: ‘Alice’ }, privateKey, { algorithm: ‘RS256’ });

 

Claims, Claims, Claims: Claims in JWTs convey specific data or rights the bearer of the token possesses. It’s essential to validate these claims rigorously. 

 

For instance, if a JWT carries a claim indicating admin access, it’s vital to cross-verify this server-side before granting any privileges. Blindly trusting incoming tokens could lead to unauthorized access.

Look at the following:

const data = jwt.verify(receivedToken, publicKey);
if (data.isAdmin && userRole !== ‘admin’) throw new Error(‘Invalid role claim!’);

 

Here, the code first verifies the received token. It then checks if a claim for admin rights exists and validates it against the user’s actual role, throwing an error if there’s a mismatch.

 

Life and Death of a Token: Just like perishable goods, tokens should have an expiration date. A token that lingers indefinitely presents an enduring security risk, especially if it falls into the wrong hands. Setting an expiration timeframe limits the window of opportunity for potential misuse.

To illustrate:

const timelyToken = jwt.sign({ user: ‘Alice’ }, ‘secret’, { expiresIn: ’24h’ });

 

This token is set to expire in 24 hours, ensuring that its potential for misuse is limited in time even if compromised.

Advanced JWT Security Measures

Blacklisting:

JWTs are designed to be stateless, meaning that once access token are issued, they can’t be invalidated until they expire. However, situations may arise where a token needs to be invalidated earlier, such as when a user logs out or changes their password.

Challenges:

  • Performance Impact: Blacklisting requires maintaining a list of invalidated tokens, which can impact performance when the list grows, especially for high-traffic systems.
  • Storage: Where and how to store the blacklist is a significant consideration. Memory storage is fast but doesn’t persist, while databases continue but introduce latency.

Possible Solutions:

  • Short-lived JWTs with Refresh Tokens: Use short-lived access tokens and longer-lived refresh tokens. Only blacklist the refresh tokens, making the list more manageable.
  • Distributed Caching Systems: Using systems like Redis to maintain the blacklist can help bridge the gap between speed and persistence.

Keep it Fresh: Regularly rotate tokens

Rotating tokens is a security measure to minimize the potential damage of a leaked token. Regularly issuing new tokens limits when a leaked token remains valid.

Challenges:

  • Implementation Complexity: Regularly rotating tokens requires mechanisms to issue, distribute, and validate the new tokens seamlessly.
  • User Experience: If not implemented correctly, users might be forced to re-authenticate more frequently.

Best Practices:

  • Use Refresh Tokens: Implement a system where short-lived JWTs are accompanied by longer-lived refresh tokens, which are used to get new JWTs without requiring the user to log in again.
  • Transparent Rotation: Ensure token rotation happens in the background without affecting the user’s session or activity.

Minimize Data: Ensure your tokens contain only the essential data required

JWTs should be lightweight, and more importantly, they shouldn’t carry sensitive data.

Risks:

  • Data Exposure: Overloading tokens can expose unnecessary user data if intercepted.
  • Performance: Larger payloads might impact network performance, especially in systems that transmit JWTs frequently.

Guidelines:

  • Never Store Sensitive Information: Avoid including data like passwords, SSNs, or any personal identification information.
  • Use Reference Data: Instead of embedding data in the token, store the data server-side and include a reference ID in the token. When the server receives the token, it can look up the full data using the reference ID.

JWT Storage: Do’s and Don’ts

Avoid localStorage: While browser storage mechanisms like localStorage or sessionStorage are easily accessible and offer a convenient method to store tokens on the client side, they come with significant risks. For instance, if an attacker successfully plants an XSS (Cross-Site Scripting) script on your site, they can extract JWTs from localStorage, leading to potential unauthorized access to session tokens.

Embrace HttpOnly Cookies: Cookies are another way to store JWTs on the client side, but they can be fortified with specific attributes. By setting a cookie as HttpOnly, you ensure that JavaScript running in the browser can’t access this cookie. This method effectively shields your token from potential XSS attacks, as the token remains invisible to any JavaScript code.

Conclusion

JWTs are a cornerstone in modern application security, effectively and securely transmitting vital information. However, mastering their intricacies and potential vulnerabilities demands more than just theoretical understanding. Effective implementation often poses challenges. Qwiet AI emerges as a valuable tool, leveraging advanced AI techniques to sift through your code and accurately highlight real vulnerabilities. To harness JWT’s potential without introducing risks, reach out for a Qwiet demo today.

 

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit: www.shiftleft.io.

Share

See for yourself – run a scan on your code right now