What is JWT None Algorithm Attack? Ways to Exploit, Examples and Impact

Master the JWT None Algorithm attack. Learn how to exploit unsigned tokens, see real-world examples, and secure your application against signature bypass.

What is JWT None Algorithm Attack? Ways to Exploit, Examples and Impact

JSON Web Tokens (JWTs) have become the gold standard for stateless authentication in modern web development. They allow applications to verify the identity of a user without storing session data on the server, making them ideal for microservices and scalable cloud architectures. However, this convenience comes with significant security responsibilities. One of the most notorious vulnerabilities in this space is the JWT "None" Algorithm attack. This flaw allows an attacker to bypass the cryptographic signature of a token, effectively granting themselves administrative access or impersonating any user on the platform.

In this guide, we will break down the mechanics of the JWT None Algorithm attack, walk through a step-by-step exploitation scenario, and discuss how you can protect your infrastructure from such critical oversight. Understanding this vulnerability is essential for any developer or security professional working with modern web APIs.

Understanding the Anatomy of a JSON Web Token (JWT)

Before we dive into the exploit, we must understand how a JWT is constructed. A JWT is composed of three distinct parts separated by dots (.):

  1. Header: Contains metadata about the token, most importantly the algorithm (alg) used for the signature.
  2. Payload: Contains the claims or data, such as the user ID, role, and expiration time.
  3. Signature: A cryptographic hash of the header and payload, used to verify that the token hasn't been tampered with.

A typical JWT looks like this: header.payload.signature. Each part is Base64URL encoded. For example, a header might look like this when decoded:

{
  "alg": "HS256",
  "typ": "JWT"
}

The alg field tells the server how to verify the signature. If it says HS256, the server uses a secret key and the HMAC-SHA256 algorithm. If it says RS256, it uses a public/private key pair. This flexibility is exactly what attackers exploit.

What is the JWT None Algorithm?

The JWT specification (RFC 7519) includes an algorithm called none. This algorithm is intended for use in environments where the integrity of the token is already guaranteed by other means, such as within a secure tunnel (TLS/SSL) where no signature is required, or during development and debugging phases.

When the alg is set to none, the signature part of the JWT is left empty. A token using the none algorithm looks like this: header.payload. (note the trailing dot).

The vulnerability occurs when a backend server is configured to accept the none algorithm from an untrusted source. If the server-side code blindly trusts the alg header provided by the client, an attacker can simply change the algorithm to none, modify the payload to gain higher privileges, and submit the token without a signature. The server, seeing none, might skip the signature verification process entirely and treat the malicious payload as valid.

How to Exploit the JWT None Algorithm Attack

Exploiting this vulnerability involves a few logical steps. Let's imagine a scenario where a web application uses a JWT to track user roles. A standard user receives a token where the payload indicates "role": "user".

Step 1: Intercept the Token

First, an attacker logs into the application and intercepts the JWT sent by the server, usually found in the Authorization header or a cookie.

GET /api/dashboard HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiam9obiIsInJvbGUiOiJ1c2VyIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Step 2: Decode and Modify the Header

The attacker decodes the first part (the header) from Base64URL.

Original Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Modified Header:

{
  "alg": "none",
  "typ": "JWT"
}

Step 3: Modify the Payload

Next, the attacker decodes the second part (the payload) and changes the claims to elevate their privileges.

Original Payload:

{
  "user": "john",
  "role": "user"
}

Modified Payload:

{
  "user": "admin",
  "role": "admin"
}

Step 4: Re-encode and Strip the Signature

The attacker Base64URL encodes the new header and payload. Crucially, they remove the signature and the final dot, or sometimes keep the dot depending on the library's implementation.

Encoded Header: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0
Encoded Payload: eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ

Malicious JWT: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ.

Step 5: Send the Malicious Request

The attacker sends the request back to the server with the forged token. If the application is vulnerable, it will see alg: none, skip the cryptographic check, and log the attacker in as the administrator.

Variations of the None Attack

Developers eventually became aware of this flaw, and many libraries started blacklisting the string none. However, attackers found ways to bypass these simple string checks using various obfuscation techniques. If a server's filter is case-sensitive or doesn't account for different encodings, the following variations might still work:

  • Case Variations: Using None, NONE, nOnE, or noNe instead of lowercase none.
  • Encoding Tricks: Using different URL encoding or Unicode characters that normalize to "none" in the backend.
  • Library-Specific Quirks: Some older libraries would accept the token if the signature part contained dummy data while the header specified none.

These variations demonstrate why robust security requires more than just a simple "if-statement" check against a single keyword.

Real-World Impact of JWT None Exploitation

The impact of a successful JWT None attack is almost always "Critical." Since JWTs are used for authentication and authorization, bypassing the signature means the attacker has full control over the identity context of the application.

  • Privilege Escalation: As shown in our example, a regular user can become an admin, gaining access to sensitive configuration, user databases, and financial records.
  • Account Takeover: An attacker can change the user_id or email claim in the payload to impersonate any other user on the system without knowing their password.
  • Data Exfiltration: With administrative access, attackers can dump entire databases or access private files stored in the cloud.
  • Stateless Persistence: Because JWTs are stateless, once a forged token is accepted, the attacker can continue to use it until it expires, and the server has no easy way to revoke it without implementing a complex denylist.

Why Do Developers Make This Mistake?

It is rarely a case of a developer intentionally allowing none. Instead, it usually stems from:

  1. Default Library Configurations: Some older versions of popular JWT libraries (like node-jsonwebtoken or certain Java JWT libs) had the none algorithm enabled by default.
  2. Improper Testing Code: Developers might enable none during local development to make testing easier and forget to disable it or change the logic before pushing to production.
  3. Generic Verification Functions: Using a verify() function that takes the algorithm as an input from the token itself rather than hardcoding the expected algorithm on the server side.

For example, a vulnerable implementation in Node.js might look like this:

// VULNERABLE CODE
const jwt = require('jsonwebtoken');

app.get('/admin', (req, res) => {
    const token = req.headers['authorization'].split(' ')[1];
    // This is dangerous because it doesn't specify the allowed algorithms
    const decoded = jwt.verify(token, secretKey);
    
    if (decoded.role === 'admin') {
        res.send("Welcome, Admin!");
    }
});

In the code above, if the token specifies alg: none, some libraries might return the decoded payload without even checking the secretKey.

How to Prevent JWT None Algorithm Attacks

Securing your application against this attack requires a defense-in-depth approach. Follow these best practices to ensure your JWT implementation is resilient:

1. Explicitly Define Allowed Algorithms

Never let the token dictate which algorithm the server should use for verification. Instead, hardcode the expected algorithm in your verification logic. Most modern libraries allow you to pass an algorithms array.

// SECURE CODE
const jwt = require('jsonwebtoken');

const options = {
    algorithms: ['HS256'] // Only allow HS256, explicitly rejecting 'none'
};

const decoded = jwt.verify(token, secretKey, options);

2. Update Your Dependencies

Ensure that you are using the latest versions of your JWT libraries. Major vulnerabilities like the none algorithm flaw were patched years ago in the most popular packages. Using outdated libraries is one of the easiest ways to leave your Jsmon monitored attack surface exposed to legacy exploits.

3. Validate the Signature Presence

Ensure your backend logic rejects any token that does not contain a signature, regardless of what the header says. If your application does not require unsigned tokens (which is true for 99% of web apps), there is no reason to ever support the none algorithm.

4. Use Strong, Secret Keys

While the none attack bypasses the key, other attacks (like brute-forcing) target the key itself. Use long, complex, and randomly generated secrets for HMAC or strong RSA/ECDSA keys for asymmetric signing.

Detecting JWT Vulnerabilities with Jsmon

Manually checking every API endpoint for JWT flaws is time-consuming and prone to human error. This is where automated reconnaissance and attack surface management come into play. Tools like Jsmon help security teams keep a constant eye on their external infrastructure.

By monitoring your subdomains, APIs, and JavaScript files, Jsmon can help you identify changes in your environment that might introduce new authentication vulnerabilities. For instance, if a new microservice is deployed with a misconfigured JWT library, early detection through infrastructure reconnaissance is key to preventing a breach.

Conclusion

The JWT None Algorithm attack is a classic example of how a technical feature, designed for specific edge cases, can become a catastrophic security hole when implemented without caution. By understanding that the alg header is user-controlled and therefore untrusted, developers can take the necessary steps to enforce strict verification policies.

Always remember: never trust client-side data, explicitly whitelist your cryptographic algorithms, and keep your libraries updated. Authentication is the gateway to your application; make sure that gateway is locked with more than just a "none" algorithm.

To proactively monitor your organization's external attack surface and catch exposures like JWT misconfigurations before attackers do, try Jsmon.