JSON Web Tokens (JWT) have been widely adopted for authentication in web applications, thanks to their simplicity and stateless nature. They allow the transmission of verified information between two parties, often used in login systems. However, despite their popularity, many security experts advise caution when using JWTs, particularly for session management.
In this article, we'll dive into the reasons why JWTs have raised concerns, and why many developers recommend alternative approaches.
What Is JWT?
A JSON Web Token (JWT) is a compact, URL-safe method for representing claims transferred between two parties. It is digitally signed, making it tamper-evident. The typical structure of a JWT includes three parts:
- Header: Specifies the signing algorithm.
- Payload: Contains claims or data.
- Signature: A hash of the header and payload to ensure integrity.
JWTs are often used for authentication. When a user logs in, the server issues a JWT that the client stores and attaches to future requests for secure resources. The server validates the token to authenticate the user, without having to maintain session data on the server.
So why do many people advise against using JWT?
1. JWT Size: It's Bigger Than You Think
One of the most notable drawbacks of using JWT is its size. JWTs carry their own payload (including claims such as user ID, roles, etc.), which means they are significantly larger than traditional session cookies.
A session cookie that stores a user ID might be just a few bytes.
A JWT, however, includes the user ID along with additional metadata, the payload, and a signature, making it much larger.
This additional size results in higher bandwidth usage since the token is sent with every request. This can be especially problematic in low-bandwidth situations or on mobile devices.
2. Token Revocation: A Major Security Issue
One of the most critical limitations of JWTs is the lack of easy token revocation. Once a JWT is issued, it remains valid until it expires, which can pose security risks.
The logout problem:
When a user logs out, you would expect that the session is invalidated immediately. But JWTs are stateless, and the server has no direct way of invalidating a token unless it's stored somewhere server-side, defeating the purpose of JWT being stateless. If a JWT has a long expiration time, an attacker could continue to use the stolen token even after the user logs out.
Stale tokens:
In a traditional session system, when a user's privileges are updated (for example, an admin is demoted to a regular user), the session on the server can immediately reflect that change. With JWTs, this doesn't happen until the token expires. This can allow a user to retain stale privileges for longer than intended, leading to potential security issues.
3. Redundant Signatures
JWTs are often praised for their digital signature capability, ensuring that the payload hasn’t been tampered with. However, modern web frameworks automatically sign and secure session cookies, which renders the JWT signature redundant in many cases.
Here’s the problem:
If you’re using JWTs in a cookie, your cookies are already signed and sometimes even encrypted by the framework.
Having both the cookie and the JWT carry a signature is overkill.
In practice, using traditional session cookies gives you the same level of security as JWTs, but without the additional complexity and size.
4. Security Vulnerabilities
JWTs are often not encrypted. This means the payload, which contains sensitive user information, is base64-encoded but not hidden. If someone can intercept the token, they can easily decode the payload to view its contents.
Vulnerabilities in certain situations:
Man-in-the-middle attacks: If the JWT is not transmitted over HTTPS, an attacker can intercept the token, gaining access to the user’s session.
Token tampering: While the signature ensures the token hasn’t been tampered with, issues arise when using weak signing algorithms. In some cases, attackers have been able to bypass JWT signatures with algorithm spoofing attacks, resulting in severe security breaches.
To mitigate these issues, it’s crucial to always use HTTPS and robust signing algorithms, but even then, certain vulnerabilities persist.
5. Lack of Built-In Expiry Control
While JWTs do offer an expiration time (exp), the expiration is client-side, meaning clients continue using the token until it expires. If a token is compromised, the attacker can use it until it reaches its expiration, no matter how much time is left.
This can cause serious security risks, especially for long-lived tokens. In contrast, traditional session management allows you to invalidate sessions immediately, providing better control over active sessions.
6. Complicating Simple Use Cases
For many authentication systems, using JWTs can be overkill. Traditional session-based authentication (using cookies and server-stored session data) handles most use cases effectively without the need for complex token management or the added risks of stateless JWTs.
For example:
If your app only needs to track logged-in users, a simple cookie-based approach provides the same security with less complexity.
Many modern web frameworks automatically manage cookies, signing, and encryption for you, making the need for JWT redundant in a standard login/logout flow.
Conclusion: When Not to Use JWT
While JWT can be useful for specific scenarios, such as API authorization or one-time data transfers, it's often not the best choice for session management in most web applications. Traditional session cookies, especially those offered by modern frameworks, are smaller, more secure, and easier to manage.
JWTs are not ideal if:
- You need easy token revocation.
- You want to avoid excessive bandwidth use.
- You’re working with sensitive, long-lived sessions.
In short, while JWT offers a stateless, self-contained approach to authentication, it introduces potential security and performance issues that many developers should carefully consider. Before adopting JWT for your project, evaluate your needs and ensure that it's the right tool for the job.
That's all for today.
And also, share your favourite web dev resources to help the beginners here!
Connect with me:@ LinkedIn and checkout my Portfolio.
Explore my YouTube Channel! If you find it useful.
Please give my GitHub Projects a star ⭐️
Thanks for 31784! 🤗
I’m proud to be a Hacktoberfest 2024 Contributor and Maintainer! Check out my badges below.
This is a submission for the 2024 Hacktoberfest Writing challenge: Maintainer Experience
Top comments (35)
A few mitigation measures/defenses for the humble JWT.
I know lots of people use JWTs as a way to not have to go off to the server and validate everything. A quick way to include a users groups or access level and that's fine, a good use case even. So long as you remember nothing on the web is truly secure once it hits the client. That's true with everything we do.
Wonderful security measures
I also wrote a blog about creating an authentication system that observes the security procedures not to overlook; including the ones listed here.
Any beginner overwhelmed can have a look. And also drop a github star(If only you found the resource useful)
If you found my content helpful or interesting, and you’d like to show your appreciation, why not buy me a coffee? It’s a small gesture that goes a long way in helping me keep creating more content for you.
Just click the button below to support:
Great insights!
If you found my content helpful or interesting, and you’d like to show your appreciation, why not buy me a coffee? It’s a small gesture that goes a long way in helping me keep creating more content for you.
Just click the button below to support:
I feel like you could have included resolutions to the concerns so that someone reading this that may not know the resolutions isn't scared away from using JWT. For example, logout is not an issue when you use short lived access tokens and a refresh token. The only issue here which is really not an issue but some may complain is the need for the consumer to check for a 401 and if it occurs, use the refresh token to get a new access token, then retry the previous request if they get a new valid token. There are SDKs/frameworks that do all that for you these days, so it's just a matter of knowing what to look for in an SDK for example that uses JWT.. ensure it covers the access token failure and retry logic.
In my experience.. the only way to go is using https and tokens in cookies with httpOnly flagged. The consumer app should not be able to access the token or decode it for any reason. "But then how do they get info like username, etc". Sure.. on login, the response body returns the details the consumer needs that are not "secure" like name, email, user id, etc. Whatever the API is willing to provide and deems OK to send back as part of the response body on login. Again, it's really simple and works very well. Where things fall off is developers that lack experience with JWT and misunderstand how to use them in a secure manner.
Plenty of large company's, including banks and medical sites use them. So they obviously work well enough to secure some of the most needed secure sites.
For those using a blacklist cache on the server to handle logout/invalidation.. I have yet to see a need for that. You provide an access token that is short lived. 30 seconds or so tops. With auto refresh/retry logic on the client, the consumer never worries about this. The one caveat is that the consumer does need to know how to handle the refresh token returning a 401 or 403. Basically send the user to a login screen again. Or.. if the API provides a response with the 401 or 403, consumer can use that response body.. for example "You're fired" could be a message sent back to an employee trying to access their company site. Server side on a request sees access of user that is now terminated.. invalidates that immediately.. 401 response. Refresh attempts a try and that logic on the server side sees status of employee as invalid and thus invalidates the refresh token and the response body that goes back to that request can carry details, error codes, etc.. that the consumer (with proper API documentation) can use to inform the user what is going on.. or.. just send them to a login screen. Login will now fail for a fired employee. It works quite well but DOES require the client side knowing what the responses mean and taking appropriate action.
This is why auto generated SDKs for clients to use vs straight raw API calls is often ideal.. so the consumers of the API don't have to code up the refresh/retry logic themselves and thus be annoyed at the extra code they have to do.
I have found that many developers are just lazy and don't want to deal with a little bit extra coding to provide a seamless integration with an API. Hence.. again.. generated SDKs so developers can avoid the need to do anything more than wire up some code to be called by the SDK when the failure(s) occur.
If you found my content helpful or interesting, and you’d like to show your appreciation, why not buy me a coffee? It’s a small gesture that goes a long way in helping me keep creating more content for you.
Just click the button below to support:
I think your solution has couple flaws. What you suggested is basically polling. Very bad from performance perspective. When you work with large applications, that is a no-go from the get go. "Server side on a request sees access of user that is now terminated" how do you verify that access? What is your data source? Database? Redis? Against what do you verify it? A list of all tokens? Or a blacklist? What do you think is faster here? :>
As a part time hacker I like JWT. Developers just make my job easier. Sometimes they give me 2 mins access window, sometimes there is no proning so there is more time to look around.
I believe this article is aimed more at junior developers.
1) Not a JWT issue: Only store essential data in JWTs. Avoid adding extra payload that can bloat the token or expose sensitive information. Keep it lightweight and, if needed, encrypt the payload. JWTs should primarily be used with private APIs to limit exposure
2) Token revocation: Use Redis to track active JWT IDs. It works well in multi-node environments and allows easy token revocation. However, bear in mind that managing revocation may reduce the stateless benefits of JWT. Opt for short-lived tokens and refresh tokens for simplicity
3) Cordova issues: Cookies are weakly supported in Cordova apps, which makes session management harder. You’re correct about using HTTP-only, secure cookies with encrypted data as a valid alternative
4) Sensitive data: Always encrypt sensitive information in both JWTs and cookies. Signed tokens can still be read unless the payload is encrypted
5) Session expiration: As mentioned in point #2, Redis can manage session expiry by setting EXPIRE on records. However, refreshing short-lived tokens might be more practical than actively managing sessions in Redis
6) Tool selection and purpose: JWT is not something to use just because it seems modern or popular. It should only be applied when it solves a specific problem, such as when you need stateless authentication in a distributed system. If simpler alternatives (like session cookies) can achieve the same goal more effectively, use them. JWT should always be part of a well-considered architecture, not a default choice for every project
If you found my content helpful or interesting, and you’d like to show your appreciation, why not buy me a coffee? It’s a small gesture that goes a long way in helping me keep creating more content for you.
Just click the button below to support:
Hi there!
Greta article!
Your article inspired me to write an article of my own trying to discuss and maybe solve the issues you've mentioned here.
More Secure JWT | A Better Experience
Adnan Babakan (he/him) ・ Oct 5
It'd be great if you let me know what you think about it.
Cheers!
Glad to hear Adnan that my articles inspired you write your first article. All the best for your journey. Do Subscribe to my YouTube Channel if you find it helpful! Subscribing is free, and it will motivate me to stay active here. 😊
Subscribe to my YouTube Channel if you find it helpful! Subscribing is free, and it will motivate me to stay active here. 😊
I think you should recommend other alternatives for auth. Great post!
If you found my content helpful or interesting, and you’d like to show your appreciation, why not buy me a coffee? It’s a small gesture that goes a long way in helping me keep creating more content for you.
Just click the button below to support:
Think like a hacker, its not if a data breach will happen, its when and how bad will it be. Be careful what you put in the payload. names, email addresses, roles and other things might be convenient but they are painless to extract from the JWT without knowing the secrets or algorithm used for signing. Far better to perform the lookup when you need the information or need to validate security rights.
I think this is a strong argument in favor of JWTs—all sensitive information should be stored encrypted, and every JWT implementation of JWT I've seen makes it trivially easy to add encryption (in addition to the cryptographic signing).
I can't say that about other ways of handling cookies.
To mitigate those issues, you can use opaque tokens. They can contain whatever you want / what security is required and be as small as you want (avoid excessive bandwidth use). Everytime the client passes the token to the backend, the BE takes that token and checks whether it’s still valid (revocation possible) and what permissions the use has.
Obviously the token itself is then not a JWT anymore.
I would state it differently, JWT are just great and I personally encourage using it, revocation is a problem indeed but it is quite easy/possible to mitigate. It is box of wonders especially with open source KeyCloak. It is the tool for SSO in my opinion at least:)
Great article btw.
I always use a trick. I always issue the token version in jwt payload and save that version on database and then compare the token version in authentication. If I want to expire the session I will just update the version in database and old jwt becomes useless.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.