Authentication: JWT usage vs session

116,994

Solution 1

JWT doesn't have a benefit over using "sessions" per se. JWTs provide a means of maintaining session state on the client instead of doing it on the server.

What people often mean when asking this is "What are the benefits of using JWTs over using Server-side sessions".

With server-side sessions, you will either have to store the session identifier in a database, or else keep it in memory and make sure that the client always hits the same server. Both of these have drawbacks. In the case of the database (or other centralised storage), this becomes a bottleneck and a thing to maintain - essentially an extra query to be done with every request.

With an in-memory solution, you limit your horizontal scaling, and sessions will be affected by network issues (clients roaming between Wifi and mobile data, servers rebooting, etc).

Moving the session to the client means that you remove the dependency on a server-side session, but it imposes its own set of challenges.

  • Storing the token securely.
  • Transporting it securely.
  • JWT sessions can sometimes be hard to invalidate.
  • Trusting the client's claim.

These issues are shared by JWTs and other client-side session mechanisms alike.

JWT, in particular, addresses the last of these. It may help to understand what a JWT is:

It is a bit of information. For user sessions, you could include the username and the time when the token expires. But it could conceivably be anything, even the session ID or the user's entire profile (please don't do that though). It has got a secure signature that prevents malicious parties from generating fake tokens (you need access to the server's private key to sign them and you can verify that they were not modified after they were signed). You send them with every request, just like a cookie or Authorization Header would be sent. In fact, they are commonly sent in the HTTP Authorization header but using a cookie is fine too.

The token is signed and so the server can verify its origin. We will assume that the server trusts its own ability to sign securely (you should use a standard library: don't try to do it yourself, and secure the server properly).

On the issue with securely transporting the token, the answer is commonly to send it via an encrypted channel, usually httpS.

Regarding securely storing the token in the client, you need to ensure that the bad guys can't get to it. This (mostly) means preventing JS from bad web sites from reading the token to send it back to them. This is mitigated using the same strategies used to mitigate other kinds of XSS attacks.

If you have a need to invalidate JWTs, there are definitely ways this can be achieved. Storing a per-user epoch for only users who have requested to have their "other sessions terminated" is a very efficient method that will probably be good enough. If an application needs per-session invalidation, then a session ID can be maintained in the same way and the "killed tokens" table can still be maintained to be much smaller than the full user table (you only need to retain records newer than the longest allowed token lifetime). So the ability to invalidate the token partially negates the benefit of client-side sessions in that you would have to maintain this session killed state. This will more than likely be a much smaller table than the original session state table, so the lookups are still more efficient though.

One other benefit of using JWT tokens is that it is reasonably easy to implement using libraries available in probably every language you can expect to have it. It is also completely divorced from your initial user authentication scheme - if you move to a fingerprint-based system, you do not need to make any changes to the session management scheme.

A more subtle benefit: Because the JWT can carry "information" and this can be accessed by the client, you can now start doing some smart things. For example, remind the user that their session will be expiring a few days before they are logged out, giving them the option to re-authenticate, based on the expiry date in the token. Whatever you can imagine.

So in short: JWTs answers some of the questions and shortcomings of other session techniques.

  1. "Cheaper" authentication because you can eliminate a DB round trip (or at least have a much smaller table to query!), which in turns enable horizontal scalability.

  2. Tamper-proof client-side claims.

While JWTs does not answer the other issues like secure storage or transport, it does not introduce any new security issues.

A lot of negativity exists around JWTs, but if you implement the same security that you would for other types of authentication, you will be fine.

One final note: It is also not Cookies vs Tokens. Cookies is a mechanism for storing and transporting bits of information and can be used to store and transport JWT tokens too.

Solution 2

The short answer is: None.

A longer version is:

I implemented JWTs for session management after reading this recommendation in the GraphQL docs:

If you aren't familiar with any of these authentication mechanisms, we recommend using express-jwt because it's simple without sacrificing any future flexibility.

Implementation was indeed simple as it only added a little bit of complexity. After a while however, I (like you) started wondering what the benefits were. It turns out there are very few (or possibly none) for JWT as far as session management goes, as this blog post explains in detail:

Stop using JWT for sessions

Solution 3

I had a similar question choosing between JWT and token + cache for user authentication.

After reading these articles, it's clear to me the benefits JWT promises do not outpace the problems it brings. So token + cache(Redis/Memcached) is the way to go for me.

Auth Headers vs JWT vs Sessions — How to Choose the Right Auth Technique for APIs

Authentication Techniques for APIs

Stop using jwt for sessions

Solution 4

My two cents, which on the way add some contrast to joepie91's famous blog post.

Considering that today's (and tomorrow's) applications are (mostly) cloud native
There's an economic benefit to Stateless JWT Authentication, which scales as the application scales:
Cloud applications incur cost with every passing second.
This cost is reduced when users no longer have to authenticate "against" a session store. Detailed below are some factors which add to the cost of an application when not using JWT:

Database Server
Running a session store 24/7 costs money.
You can not get away with local storage / memory based solutions in the world of K8S, as pods are ephemeral.
Sticky sessions will not fare well for the exact same reason.

Storage
Storing data costs money. storing data in a SSD costs even more.
Session related operations need to be resolved quickly, so an optical drive is not an option.

I/O
Some cloud providers charge money for Disc related I/O.

Download
Circa 2022, it is safe to assume that the API and session store are separate server instances.
Some cloud providers charge for downloading information from one instance to another.

Scaling the session store
This affects all aforementioned factors.

Solution 5

Yet another slightly different perspective that may be useful if you are on AWS.

We had implemented PHP5.x session storage on AWS ElastiCache to centralise session storage across multiple servers.

It worked perfected until we moved to PHP7. It was difficult to configure for PHP7 and we were plagued with intermittent issues where it seemed that the session "failed/mismatched/got a bit confused" for a particular user and then they could not log in on that device until the old session expired.

We moved to using DynamoDb to store the session and no more issues. It is marginally slower but only noticeable at login (session storage) stage.

While this was going on, we implemented AWS cognito to replace our authentication and started to use the API-Gateway to deliver content via lambda python functions.

We use the PHP SDK to authenticate with Cognito and then we store the JWT in a cookie but still also use the PHP session to keep our legacy code working.

Now we have two stacks and the best of both worlds: PHP7 does it's bit and gets the main content to the user (very quickly). Then JS takes over and provides additional content using the JWT.

What I think is great about JWT is the fact that it can be passed around between these two stacks and used to authenticate the user in both cases.

Now we are wondering if it is worthwhile taking the plunge and switching over to the new JWT system entirely?

In PHP, we still use our legacy session but we also pass the token to cognito to authenticate it. It's a bit of extra security that is probably not necessary but it gives a warm cozy feeling. Then again, there are costs and maintenance with dynamoDb that could be saved.

Share:
116,994

Related videos on Youtube

Pourya8366
Author by

Pourya8366

I love everything related to Tech!

Updated on July 08, 2022

Comments

  • Pourya8366
    Pourya8366 almost 2 years

    What is the advantage of using JWTs over sessions in situations like authentication?

    Is it used as a standalone approach or is it used in the session?

  • Xeoncross
    Xeoncross over 5 years
    It's worth noting that server-side sessions don't have to store any information on the server either. The server can use the client as the store in the same way as the JWT does. The real difference is in 1) avoiding browser security rules by passing the value as request header other than a cookie header, and 2) having a standardized format with JWT.
  • Jessica
    Jessica almost 5 years
    Would you say it's safe to store a jwt in local storage? If not, where is a safe place to save it so that the user stays logged in?
  • tobiasBora
    tobiasBora over 4 years
    In your comment you do not talk about cache based solution + session token. It sounds to me "better" than JWT + "killed tokens" table, because with this "killed tokens" table, you need anyway a DB access, that you will have also with sessions + cache (that is small as well). And persisting JWT is more painfull to implement than persisting sessions, because you need to play with a refresh_token (so two tokens to maintain)... Any comment would be really appreciated... especially if you have some number to show how JWT + kill_table is more efficient than sessions + cache ;-)
  • The Tahaan
    The Tahaan over 4 years
    The difference is that a sessions table holds an entry for every single session. Could be millions of users. A killed tokens table only needs one row for a token if it was killed, and that can be reduced even further by removing the row if that token is expired. So the killed token lookup is across a much smaller table. In real world examples the performance difference is several orders of magnitude for large userbases.
  • Harke
    Harke over 4 years
    @TheTahaan localStorage is not recommended to store JWTs. The link that you shared also mentions that. This blog has good explanation as to why JWT should not be stored in localStorage.
  • crackpotHouseplant
    crackpotHouseplant about 4 years
    "You can not get away with memory based solutions in the world of K8S, as pods are ephemeral" Not sure what you mean by this. Redis definitely works in a K8S environment, and a redis pod failing frequently enough to affect your users seems very unlikely.
  • Eyal Perry
    Eyal Perry about 4 years
    @quietContest I personally prefer not to deal with likelihood when building software. BTW, solution stability aside, an attack can cause software to fail and pods to restart- which would result in session loss. I'd opt for a JWT based solution for that reason.
  • crackpotHouseplant
    crackpotHouseplant about 4 years
    "I personally prefer not to deal with likelihood when building software". I think we would all prefer that, which is why we shouldn't architect systems that rely on in-memory data stores never failing, because the likelihood of that seems reasonably high. As to your other point, if you have an attacker that is able to consistently shut off your redis instance, the solution to that probably doesn't need to involve using JWTs.
  • Eyal Perry
    Eyal Perry about 4 years
    @quietContest consistently or a once in a lifetime event are the same to me in this aspect. i.e. a well placed DDoS attack can cause the server to "log users out". This doesn't do well for the software's reliability reputation. I think redis is overkill for session management anyway. It costs and needs to be scaled, whereas (safely) storing a JWT in a cookie does not.
  • Eyal Perry
    Eyal Perry about 4 years
    @quietContest thanks for your input, love the discussion!
  • The Fool
    The Fool almost 4 years
    What if you need to to work cross domain? AFAIK cookies cannot be used in that case.
  • Guill
    Guill over 3 years
    In this case you are sacrificing security against XSS provided by the browser. Cross site session should be avoided if at all possible IMHO. Mind that abc.example.com and example.com are normally considered by browsers as being the same site.
  • Ham
    Ham over 3 years
    If your backend server maintains secret for each logged-in user to generate JWT (e.g. stored in cache server) , the alternative to invalidate a JWT is to delete the secret stored in the server (even the tokens haven't expired yet) , so all tokens generated with the deleted secret are automatically invalid, when user login next time, the server generates another new JWT for the user. By doing so it is no longer necessary to store entire JWT. on server side
  • Ham
    Ham over 3 years
    This article also describes how to perform XSS attack through LocalStorage in your browser, for those who are confused about where to store sensitive data like JWT.
  • x-yuri
    x-yuri over 3 years
    Doesn't sound beautiful, but supposedly pragmatic. But from what I can see, particularly in your case JWT-tokens are less secure (owing to possibility of XSS attachks), than server-side sessions. Because the latter can be stored in secure httponly samesite=lax or strict cookies.
  • x-yuri
    x-yuri over 3 years
    It appears that if you've got a XSS vulnerability, SameSite won't help against CSRF. As such server-side sessions might be vulnerable to CSRF. And so seemingly client-side sessions are not less secure.
  • Enigma Plus
    Enigma Plus over 3 years
    I think I follow what you are saying @x-yuri but I also think we are safe because the PHP stack does not take any "instruction" from the JWT cookie. It just logs in via the session and saves the JWT for the other stack to use. Or am I missing something?
  • x-yuri
    x-yuri over 3 years
    Not so long ago I thought that JWT tokens (or rather client-side sessions) are less secure than the server-side ones. Because JWT's are vulnerable to XSS attacks. With server-side sessions if you use a httponly cookie, that possibility is eliminated. But server-side sessions might be vulnerable to CSRF. Unless you use a cookie with SameSite=Lax or Strict. Or so I thought. But it appears if you have an XSS vulnerability, that makes you vulnerable to CSRF as well.
  • x-yuri
    x-yuri over 3 years
    ...As such I now think there's no clear winner. On one hand I can say, why not store the token in local storage? Storing it in a cookie you might be vulnerable to CSRF. Unless you're sure you're not vulnerable to XSS and the cookie has the SameSite attribute. On the other hand, you must take measures to prevent XSS anyway. As such storing it in local storage makes more sense. Since you don't have to even consider CSRF. A good answer on this matter.
  • x-yuri
    x-yuri over 3 years
    ...P.S. It's not about taking instructions from a cookie, it's about "how do you know if a request with a cookie is triggered by a user, not by an attacker?" E.g. what if an attacker embeds a piece of code on your site that does a POST request on behalf of a user to https://yourdomain.com/api/delete/everything. That would be XSS+CSRF.
  • mercury
    mercury over 3 years
    Do not save it on lacal storage
  • CyberSrikanth
    CyberSrikanth almost 3 years
    @Harke If you site is vulnerable to XSS, then storing tokens in cookies also won't help you, since attacker can exploit you by session riding attack Check this blog. We can safely store tokens in local storage.
  • Gherman
    Gherman about 2 years
    If XSS did happen even httpOnly cookies will not save user from attacks, at this point not much will help. On the other hand cookies are susceptible to CSRF and JWT in local storage is not.