Preventing JWT Signature Bypass via the None Algorithm

This guide explains how attackers use the alg none field in a JSON Web Token header to bypass signature verification and escalate privileges on a server.

A JSON Web Token consists of three segments separated by dots. These are the header, the payload and the signature. Each segment is a string encoded using base64url. It is a common error to mistake this encoding for encryption. Base64url is merely a way to represent binary data as text so it can be passed in an HTTP header or a URL without breaking the protocol.

The payload contains claims, which are statements about an entity and additional data. Because this payload is only encoded, any person who intercepts the token can decode it in seconds using standard tools. If you place a secret, such as a private API key or a password, inside the payload, you have effectively made that secret public to anyone with a browser. The security of a JWT does not come from hiding the data, but from ensuring the data has not been altered. This is the purpose of the third segment, the signature. The server creates this signature by hashing the header and payload using a secret key. When you send the token back, the server repeats the process to see if the result matches the signature provided.

The trust gap

The vulnerability begins in the header. The header tells the server which algorithm was used to generate the signature. This is stored in a field called alg. A naive server reads this field and then chooses the corresponding verification method. This creates a situation where the attacker, who controls the token, also controls the security policy of the server.

The most blatant version of this flaw involves setting the algorithm field to none. The specification for JWT allows for unsigned tokens in specific contexts. When a server sees the algorithm set to none, it may conclude that no signature is required for the token to be valid. An attacker can take an existing token and decode the header and payload. They might change their user role from user to administrator in the payload. They then modify the header so the algorithm field reads none.

To complete the attack, you remove the third segment entirely or leave it empty, keeping only the trailing dot. If the server trusts the header blindly, it sees the none value and skips the signature check entirely. It accepts the modified payload as authentic because the token told the server that no signature was necessary. This is a failure of logic where the verifier asks the untrusted input how it should be verified.

Hardening the verifier

You prevent this by removing the server's trust in the header. The algorithm must not be a suggestion provided by the client. It must be a requirement enforced by the server. You pin the expected algorithm in your server configuration. If your system is designed to use RS256, you configure the verification logic to accept only RS256 signatures.

If a token arrives with any other value in the algorithm field, including none, the server must reject it immediately without looking at the payload. You do not ask the token what it is; you tell the token what it must be. This ensures that an attacker cannot downgrade the security level of the connection by simply changing a string in the header.

You should also ensure your library does not allow the none algorithm by default. Some older libraries prioritised flexibility over security and allowed any algorithm specified in the header. You explicitly disable this behaviour. By pinning the algorithm to a specific, secure choice on the server side, you render the header's alg field irrelevant for security decisions. The server becomes the sole authority on how verification is performed, which is where that authority belongs.

Try it: JWT decoder and inspector

Sources

Every link below is checked before this page is published.

  1. RFC 7519 - JSON Web Token (JWT)
  2. RFC 8725 - JSON Web Token Best Current Practices

More from the Format Notebook