Skip to content
loading...

re: How I Fixed JWT Security Flaws in 3 Steps VIEW POST

FULL DISCUSSION
 

No. Instead, the backend should set the JWT as a cookie in the user browser. Make sure you flag it as Secure and httpOnly cookie. And SameSite cookie. Boy, that's a multi-flavor cookie. This way, the JWT will be available to the backend in all subsequent requests, while remaining outside the reach of potentially dirty JS hands.

This type of advice will sadly not help the reader. Here's why:

  • If the reader is building a SPA hosted on a static site (S3, Netlify, ...) there is no way to set a cookie. The only option is to store the token in memory, which still has a risk for XSS attacks.
  • If the reader has a backend which sets cookies, then then you can skip JWTs all together. Just create a session. No need to reinvent the wheel. Sessions are a solved problem and have battle tested tooling across every platform. JWTs provide zero value here. If your backend then needs to call APIs it could store any token it needs in the session and extract it from there.
 

Hi Sandrino, thanks for taking the time to contribute to the discussion!

The whole point of the discussion is when we have a backend securely authenticating a user. JWT won't apply to Frontend-only scenarios.

A large portion of web apps nowadays have a backend, so I wouldn't agree that the discussion here is useless...

About your second topic, it's a discussion beyond the purpose of my article. It's fair for you to prefer using Session IDs, but many people have a different view.

On whether JWT is a good authentication solution or not. I'm going to need to differ on this statement:

"JWTs provide zero value"

First, sessions are just cookies, they're no different. Storing a Session ID or a JWT as a cookie in the browser is essentially the same thing.

The advantage of a JWT is that, once the backend receives it in the request header as a cookie, it doesn't need to go anyplace get more info. It's self-contained.

This is a property called stateless and it plays very well in distributed environments designed for variable demand and smoother scalability.

Whereas with a Session ID, the backend still needs to ask a storage engine to authenticate who is the owner of that session. It's a design that is more difficult to scale.

 

The whole point of the discussion is when we have a backend securely authenticating a user. JWT won't apply to Frontend-only scenarios.

I'm not referring to frontend only scenarios, there is indeed no such thing as frontend/client-side authentication. What I'm referring to is modern applications where the frontend is hosted on a static file server and the backend is an API often running on a different (sub)domain.

An application could be running on AWS S3 on acme.com which then needs to call an API (eg: Heroku) an api.acme.com. In that case a JWT can be used to serve as a bearer token, but the site running on acme.com has no backend which can set cookies. A backend and an API can be the same or different concepts.

About your second topic, it's a discussion beyond the purpose of my article. It's fair for you to prefer using Session IDs, but many people have a different view.

The advantage of a JWT is that, once the backend receives it in the request header as a cookie, it doesn't need to go anyplace get more info. It's self-contained.

This is a property called stateless and it plays very well in distributed environments designed for variable demand and smoother scalability.

I'm not talking about Session IDs, I'm talking about sessions. Session use cookies and they can contain a session ID where a backend data store is used or they can be self contained, where the data is stored in a cookie and then encrypted. express-sessions is a good example of this.

Sessions in every platform already have all the required tools to make them work for many different use cases:

  • Session lifetime (absolute and sliding expiration)
  • Destroying a session
  • Session stores (cookie - self contained, Redis, MongoDB, ...)

First, sessions are just cookies, they're no different. Storing a Session ID or a JWT as a cookie in the browser is essentially the same thing.

It's not:

  • JWTs are signed and not encrypted. Anyone can inspect the data by decoding the token. You would need JWE to support this. Sessions are often encrypted if the data is persisted in a cookie.
  • JWTs don't have support for sliding expiration, they only have the notion of absolute expiration. You would need to reissue new tokens each time someone is active if you want support for sliding expiration. Sessions have this out of the box.
  • Browsers like Safari have cookie size limitations on the domain level. A JWT often provides lots of overhead and can take up a significant amount of data (1KB is big if you need to consider Safari limitations). With a sessions this can be addressed with a backing data store.

We're getting way way beyond the purpose of my article, but let's cover it quickly.

I see there are maybe some conceptual confusions.

When api.domain.com sets a cookie, it doesn't need to be available for domain.com. When domain.com fires a subsequent request to API, the cookie will be sent along with it. It's the API that needs the JWT, not domain.com. This can work if you set the API to accept CORS.

What I mean is that a session uses a cookie the same way its proposed for JWT to use it. Obviously they are different implementations.

The problem with sessions is not encryption, but what can be extracted from them. JWT can store minimal user object, so that API doesn't necessarily have to reach a database for that.

code of conduct - report abuse