Update - June 19, 2016: A lot of people have been suggesting the same "solutions" to the problems below, but none of them are practical. I've published a new post with a slightly sarcastic flowchart -…
Article word count: 2440
HN Discussion: https://news.ycombinator.com/item?id=18353874
Posted by enraged_camel
(karma: 11948)Post stats: Points: 113 - Comments: 76 - 2018-11-01T13:56:10Z
\#HackerNews #2016 #for
Update - June 19, 2016: A lot of people have been suggesting the same "solutions" to the problems below, but none of them are practical. Iʼve published a new post with a slightly sarcastic flowchart - please have a look at it before suggesting a solution.
Unfortunately, lately Iʼve seen more and more people recommending to use JWT (JSON Web Tokens) for managing user sessions in their web applications. This is a terrible, terrible idea, and in this post, Iʼll explain why.
Just to prevent any confusion, Iʼll define a few terms first:
\* Stateless JWT: A JWT token that contains the session data, encoded directly into the token.
\* Stateful JWT: A JWT token that contains just a reference or ID for the session. The session data is stored server-side.
\* Session token/cookie: A standard (optionally signed) session ID, like web frameworks have been using for a long time. The session data is stored server-side.
To be clear: This article does not argue that you should never use JWT - just that it isnʼt suitable as a session mechanism, and that it is dangerous to use it like that. Valid usecases do exist for them, in other areas. At the end of this article, Iʼll briefly go into those other usecases.
A note upfront
A lot of people mistakenly try to compare "cookies vs. JWT". This comparison makes no sense at all, and itʼs comparing apples to oranges - cookies are a storage mechanism, whereas JWT tokens are cryptographically signed tokens.
They arenʼt opposites - rather, they can be used either together or independently. The correct comparisons are "sessions vs. JWT" and "cookies vs. Local Storage".
In this particular article, I will be comparing sessions to JWT tokens, and occasionally go into "cookies vs. Local Storage" as well where it makes sense to do so.
Claimed advantages of JWT
When people recommend JWT, they usually claim one or more of the following benefits:
\* Easier to (horizontally) scale
\* Easier to use
\* More flexible
\* More secure
\* Built-in expiration functionality
\* No need to ask users for ʼcookie consentʼ
\* Prevents CSRF
\* Works better on mobile
\* Works for users that block cookies
Iʼll address each of these claims - and why they are wrong or misleading - individually. Some of the explanations below may be a little vague; thatʼs primarily because the claims themselves are vague. Iʼll happily update it to address more specific claims; you can find my contact details at the bottom of this article.Easier to (horizontally) scale
This is the only claim in the list that is technically somewhat true, but only if you are using stateless JWT tokens. The reality, however, is that almost nobody actually needs this kind of scalability - there are many easier ways to scale up, and unless you are operating at the size of Reddit, you will not need ʼstateless sessionsʼ.
Some examples of scaling stateful sessions:
1. Once you run multiple backend processes on a server: A Redis daemon (on that server) for session storage.
2. Once you run on multiple servers: A dedicated server running Redis just for session storage.
3. Once you run on multiple servers, in multiple clusters: Sticky sessions.
These are all scenarios that are well-supported by existing software. Your application is very unlikely to ever go beyond the second step.
Perhaps youʼre thinking that you should "future-proof" your application, in case you do ever scale up beyond that. In practice, however, itʼs fairly trivial to replace the session mechanism at a later point, with the only cost being logging out every user once, when you make the transition. Itʼs just not worth it to implement JWT upfront, especially considering the downsides that Iʼll get to later.Easier to use
They really arenʼt. You will have to deal with session management yourself, on both the client and the server side, whereas standard session cookies just work, out of the box. JWT isnʼt easier in any way.More flexible
I have yet to see somebody actually explain how JWT is more flexible. Almost every major session implementation lets you store arbitrary data for the session anyway, and this is no different from how JWT works. As far as I can tell, this is just used as a buzzword. If you disagree, feel free to contact me with examples.More secure
A lot of people think that JWT tokens are "more secure" because they use cryptography. While signed cookies are more secure than unsigned cookies, this is in no way unique to JWT, and good session implementations use signed cookies as well.
"It uses cryptography" doesnʼt magically make something more secure either; it must serve a specific purpose, and be an effective solution for that specific purpose. Incorrectly used cryptography can, in fact, make something less secure.
Another explanation of the "more secure" argument that I hear a lot, is that "they are not sent as a cookie". This makes absolutely no sense - a cookie is just a HTTP header, and thereʼs nothing insecure about using cookies. In fact, cookies are especially well-protected against eg. malicious client-side code, something Iʼll get into later.
If you are concerned about somebody intercepting your session cookie, you should just be using TLS instead - any kind of session implementation will be interceptable if you donʼt use TLS, including JWT.Built-in expiration functionality
This is nonsense, and not a useful feature. Expiration can be implemented server-side just as well, and many implementations do. Server-side expiration is preferable, in fact - it allows your application to clean up session data that it doesnʼt need anymore, something you canʼt do if you use stateful JWT tokens and rely on their expiration mechanism.No need to ask users for ʼcookie consentʼ
Completely wrong. Thereʼs no such thing as a "cookie law" - the various laws concerning cookies actually cover any kind of persistent identifier that isnʼt strictly necessary for the functioning of the service. Any session mechanism you can think of will be covered by this.
In a nutshell:
\* If you are using a session or token for functional purposes (eg. keeping a user logged in), then you donʼt need to ask for user consent, regardless of how you store that session.
\* If you are using a session or token for other purposes (eg. analytics or tracking), then you do need to ask for user consent, regardless of how you store that session.
It doesnʼt, really. There are roughly two ways to store a JWT:
\* In a cookie: Now you are still vulnerable to CSRF attacks, and still need protection against it.
The only correct CSRF mitigation is a CSRF token. The session mechanism is not relevant here.Works better on mobile
Nonsense. Every mobile browser still in use supports cookies, and thus sessions. The same goes for every major mobile development framework, and any serious HTTP library. This is just not a problem at all.Works for users that block cookies
Unlikely. Users donʼt just block cookies, they typically block all means of persistence. That includes Local Storage, and any other storage mechanism that would allow you to persist a session (with or without using JWT). Whether you use JWT simply doesnʼt matter here, itʼs an entirely separate problem - and trying to get authentication to work without cookies is a bit of a lost cause.
On top of that, users that block all cookies typically understand that this will break authentication functionality for them, and individually unblock cookies for sites where they care about this. Itʼs simply not a problem that you, as a web developer, need to be solving; a much better solution is to explain to your users why your site requires cookies to work.
Now that Iʼve covered all the common claims and why theyʼre wrong, you might think "oh, thatʼs not a big deal, it still doesnʼt matter that I use JWT even if it doesnʼt help me", and youʼd be wrong. There are quite a few downsides to using JWT as a session mechanism, several of them being serious security issues.They take up more space
JWT tokens are not exactly small. Especially when using stateless JWT tokens, where all the data is encoded directly into the token, you will quickly exceed the size limit of a cookie or URL. You might decide to store them in Local Storage instead - however...They are less secure
When storing your JWT in a cookie, itʼs no different from any other session identifier. But when youʼre storing your JWT elsewhere, you are now vulnerable to a new class of attacks, described in this article (specifically, the "Storing sessions" section):
We pick up where we left off: back at local storage, an awesome HTML5 addition that adds a key/value store to browsers and cookies. So should we store JWTs in local storage? It might make sense given the size that these tokens can reach. Cookies typically top out somewhere around 4k of storage. For a large-sized token, a cookie might be out of the question and local storage would be the obvious solution. However, local storage doesn’t provide any of the same security mechanisms that cookies do.
After all the trouble those engineers went through to make sure nobody is going to make off with our cookie jar, here we are trying to ignore all the fancy tricks they’ve given us. That seems a little backwards to me.
Simply put, using cookies is not optional, regardless of whether you use JWT or not.You cannot invalidate individual JWT tokens
And there are more security problems. Unlike sessions - which can be invalidated by the server whenever it feels like it - individual stateless JWT tokens cannot be invalidated. By design, they will be valid until they expire, no matter what happens. This means that you cannot, for example, invalidate the session of an attacker after detecting a compromise. You also cannot invalidate old sessions when a user changes their password.
You are essentially powerless, and cannot ʼkillʼ a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with.Data goes stale
Somewhat related to this issue, and yet another potential security issue. Like in a cache, the data in a stateless token will eventually ʼgo staleʼ, and no longer reflect the latest version of the data in your database.
This can mean that a token contains some outdated information like an old website URL that somebody changed in their profile - but more seriously, it can also mean somebody has a token with a role of admin, even though youʼve just revoked their admin role. Because you canʼt invalidate tokens either, thereʼs no way for you to remove their administrator access, short of shutting down the entire system.Implementations are less battle-tested or non-existent
You might think that all these issues are just with stateless JWT tokens, and youʼd be mostly right. However, using a stateful token is basically equivalent to a regular session cookie... but without the battle-tested implementations.
Existing session implementations (eg. express-session for Express) have been running in production for many, many years, and their security has been improved a lot because of that. You donʼt get those benefits when using JWT tokens as makeshift session cookies - you will either have to roll your own implementation (and most likely introduce vulnerabilities in the process), or use a third-party implementation that hasnʼt seen much real-world use.
Stateless JWT tokens cannot be invalidated or updated, and will introduce either size issues or security issues depending on where you store them. Stateful JWT tokens are functionally the same as session cookies, but without the battle-tested and well-reviewed implementations or client support.
Unless you work on a Reddit-scale application, thereʼs no reason to be using JWT tokens as a session mechanism. Just use sessions.
So... what is JWT good for, then?
At the start of this article, I said that there are good usecases for JWT, but that theyʼre just not suitable as a session mechanism. This still holds true; the usecases where JWT is particularly effective are typically usecases where they are used as a single-use authorization token.
From the JSON Web Token specification:JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. [...] enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.
In this context, "claim" can be something like a ʼcommandʼ, a one-time authorization, or basically any other scenario that you can word as:Hello Server B, Server A told me that I could <claim goes here>, and hereʼs the (cryptographic) proof.
For example, you might run a file-hosting service where the user has to authenticate to download their files, but the files themselves are served by a separate, stateless "download server". In this case, you might want to have your application server (Server A) issue single-use "download tokens", that the client can then use to download the file from a download server (Server B).
When using JWT in this manner, there are a few specific properties:
\* The tokens are short-lived. They only need to be valid for a few minutes, to allow a client to initiate the download.
\* The token is only expected to be used once. The application server would issue a new token for every download, so any one token is just used to request a file once, and then thrown away. Thereʼs no persistent state, at all.
\* The application server still uses sessions. Itʼs just the download server that uses tokens to authorize individual downloads, because it doesnʼt need persistent state.
As you can see here, itʼs completely reasonable to combine sessions and JWT tokens - they each have their own purpose, and sometimes you need both. Just donʼt use JWT for persistent, long-lived data.
HackerNewsBot debug: Calculated post rank: 100 - Loop: 67 - Rank min: 100 - Author rank: 26
Stop using JWT for sessions - joepie91's Ramblingscryto.net