Everything you should know about JWT’s security

Alireza Bolbolabadi
9 min readMay 7, 2019

--

JWT Authentication Security

Today, the use of web-based systems is increasingly growing. One of the most important ways which secure the operations of web-based system users is authentication. There are many ways to authenticate users. In this paper, we discuss one of them called the JSON Web Token(JWT).

Introduction to JWT

As the JWT’s website says:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compressed and self-contained way for securely transferring information between participants as a JSON object. This information can be checked and conferred 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.
In its compact form, JSON Web Tokens consist of three sections separated by dots (.), which are:
• Header
• Payload
• Signature

Token-Based Authentication

Adnan Kukic at his paper explains:

Token-based authentication has reached prevalence over the last few years due to the growth of single-page applications, web APIs, and the Internet of Things (IoT). When we talk about authentication with tokens, we usually talk about authentication with JSON Web Tokens (JWTs). While there are different ways to implement tokens, JWTs have become the actual standard.
Token-based authentication is stateless. The server does not store a record of which JWTs have been issued or which users are logged in. Alternately, every request to the server is followed by a token which the server uses to check the authenticity of the request. The token is usually sent as an addition Authorization header in the form of Bearer {JWT}, but can additionally be sent in the body of a POST request or even as a query parameter. Let’s see how this flow works:

1. The user enters their login information.
2. The server validates the information are true and returns a signed token.
3. This token is saved client-side, most generally in local storage — but can be saved in session storage or a cookie as fine.
4. Following requests to the server include this token as a new Authorization header or through one of the other techniques discussed earlier.
5. The server decodes the JWT and if the token is true processes the request.
6. Once a user logs out, the token is terminated client-side, no interaction with the server is needed.

Attacking JWTs

Sjoerd Langkemper at his website clarify probable JWT attacks:

If you have an application that uses JWT for authentication, there are several things you can try to test the security of the authentication layer.

Check for sensitive data in the JWT
JWTs are base64-encoded data. They are easily decoded, for example by applying the website JWT.io. There may be sensitive data saved in the JWT, that is simply recognized this way.

Change the signing algorithm
JWTs should be signed to restrict users from modifying the data inside. There are many algorithms that can be used for signing, for example using an HMAC or using RSA signing. The JWT header includes the algorithm used to sign the JWT, and one defect of some algorithms is that they believe in this JWT header, even though it can be managed by the client. If this vulnerability is present, the client can generate its own tokens, something that the signature is meant to prevent.

Changing the algorithm to none
A JWT header looks like this:
{
“alg”: “HS512”,
“typ”: “JWT”
}
The alg field here shows the algorithm applied to sign the JWT. One specific “algorithm” that all JWT libraries should support is none, for no signature at all. If we define none as the algorithm in the header and leave out the signature, some implementations may allow our JWT as rightly signed.

Changing the algorithm from RS256 to HS256
The algorithm HS256 uses a secret key to sign and validate each message. The algorithm RS256 uses a private key to sign messages, and a public key to verify them. If we modify the algorithm from RS256 to HS256, the signature is now verified using the HS256 algorithm using the public key as a secret key. Since the public key is not secret at all, we can rightly sign such messages.

Crack the key
As already mentioned, the HS512 algorithm uses a secret key to sign and validate messages. If we recognize this key, we can build our own signed messages. If the key is not enough strong it may break it using a brute-force or dictionary attack. By analyzing a lot of keys on a JWT and investigating whether the signature is correct we can discover the secret key. This can be done offline, once we have obtained a JWT.
There are several tools that can brute force the HS512 signature on a JWT:
• jwtbrute, a .NET implementation.
• PyJWT to do the decoding in python
• John the Ripper

Cookie-Based authentication

Adnan Kukic introduces another authentication method:

Cookie-based authentication has been the default for managing user authentication for a long time.
Cookie-based authentication is stateful. This indicates that an authentication record or session must be kept both server and client-side. The server requires to keep track of active sessions in a database, while on the front-end a cookie is generated that holds a session identifier, so the name cookie-based authentication. Let’s look at the flow of regular cookie-based authentication:
1. The user enters their login information.
2. The server validates the information are correct and generates a session which is then saved in a database.
3. A cookie with the session ID is stored in the user’s browser.
4. On the following requests, the session ID is verified against the database and if confirmed the request processed.
5. Once a user logs out of the app, the session is terminated both client-side and server-side.

Advantages of Token-Based Authentication

Adnan Kukic believes in that:

Knowing how something works is only half the battle. Next, we’ll show the reasons why token authentication is better than the regular cookie-based method.

Stateless, Scalable, and Decoupled
Maybe the biggest benefit to using tokens over cookies is the point that token authentication is stateless. The back-end does not require to hold a record of tokens. Each token is self-contained, including all the information needed to verify it’s validity as well as convey user data through claims.
The server’s only role, then, becomes to sign tokens on a successful login request and validate that incoming tokens are true. In fact, the server does not even require to sign tokens. Third party services such as Auth0 can manage the issuing of tokens and then the server only requires to check the validity of the token.

Cross Domain and CORS
Cookies work fine with single domains and sub-domains, but when it comes to handling cookies over different domains, it can get difficult. By contrast, a token-based method with CORS enabled makes it useless to expose APIs to different services and domains. Since the JWT is needed and verified with each and every call to the back-end, as long as there is a true token, requests can be processed.

Saving Data in the JWT
With a cookie-based method, you easily save the session id in a cookie. JWTs, on the other hand, allows you to save any kind of metadata, as long as it’s correct JSON. The JWT spec defines various kinds of claims that can be involved such as reserved, public and private.
In reality, what this proposes is that a JWT can include any kind of data. Based on your use case you may decide to make the minimum amount of claims such as the user id and expiration of the token, or you may choose to involve extra claims such as the user’s email address, who issued the token, scopes or permissions for the user, and more.

Performance
When applying the cookie-based authentication, the back-end has to do a search, whether that be a traditional SQL database or a NoSQL alternative, and the round trip is likely to take longer compared to decoding a token. Moreover, since you can save extra information inside the JWT, such as the user’s permission level, you can keep yourself extra search calls to get and process the requested data.

Mobile Ready
Novel APIs do not only communicate with the browser. Implemented correctly a single API can work both the browser and native mobile platforms like iOS and Android. Native mobile platforms and cookies do not work together well. While possible, there are many restrictions to using cookies with mobile platforms. But Tokens are much simpler to implement on both iOS and Android. Tokens are also simpler to implement for the Internet of Things applications and services that do not have an idea of a cookie store.

Common Concerns about JWT

In this part, we’ll investigate some general concerns about token authentication. The key focus here will be security but we’ll consider use cases concerning token size, storage and encryption.

JWT Size
The biggest defect of token authentication is the size of JWTs. A session cookie is approximately small compared to even the smallest JWT. Based on your use case, the size of the token could become troublesome if you add many claims to it. Remember, each request to the server must involve the JWT along with it.

Where to Save Tokens?
With token-based auth, you can choose where to save the JWT. Usually, the JWT is saved in the browser’s local storage and this acts well for most use cases. There are some concerns with saving JWTs in local storage to know. Unlike cookies, local storage is sandboxed to a particular domain and its data cannot be obtained by any other domain consisting sub-domains.
You can save the token in a cookie alternatively, but the max size of a cookie is only 4kb so that may be troublesome if you have many claims appended to the token. Furthermore, you can save the token in session storage which is similar to local storage but is cleared as soon as the user closes the browser.

JWT session Storage and local Storage Security
Web Storage (local Storage/session Storage) is available through JavaScript on the same domain. This indicates that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks.
To stop XSS, the usual response is to escape and encode all untrusted information. Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their awareness. So organizations recommend not to save anything of value or trust any data in web storage. This involves session identifiers and tokens.
Web Storage does not apply any secure standards during transfer. Whoever reads Web Storage and uses it must be careful to ensure they always send the JWT over HTTPS and never HTTP.

JWT Cookie Storage Security

Cookies are not accessible through Javascript when using the HttpOnly cookie flag and are safe from XSS. You can also set the secure cookie flag to send a cookie only using HTTPS. This is one of the principal purposes that cookies have been used in the past to save tokens or session data. Present developers are doubtful about using cookies because they traditionally save the state’s needs on the server, so breaking down the best RESTful methods is required. Cookies As a storage mechanism, do not need to store the state on the server, if you keep a JWT in a cookie. This is because JWT measures everything the server offers to serve the request.
However, cookies are vulnerable to cross-site request forgery (CSRF). A CSRF attack is a type of attack that happens when a malicious web site, email, or blog makes a user’s web browser to execute an unwanted action on a trusted site on which the user is currently authenticated. CSRF can be blocked by using synchronized token patterns. This sounds complex, but all modern web frameworks have support for this.
Improving your web app framework’s CSRF protection makes cookies rock solid for storing a JWT. CSRF can also be partly prevented by controlling the HTTP Referer and Origin header from your API. CSRF attacks will have Referer and Origin headers that are unrelated to your application.
Even though they are more reliable to save your JWT, cookies can cause some developer headaches, based on if your applications require cross-domain access to work. Just be conscious that cookies have extra properties (Domain/Path) that can be altered to permit you to specify where the cookie is permitted to be sent. Using AJAX, your server side can also notify browsers whether credentials (including Cookies) should be sent with requests with CORS.

At the following table we have compared the mentioned storages:

JWT’s Storage Security

Conclusion

Both of the saving mechanisms have their own pros and cons as mentioned. Based on your work and the technology or framework which is used, you should prefer one of those, but it’s needed to implement mentioned necessary security.

--

--