
JWTs: A secure and stateless way to implement authentication - Dirak
https://medium.com/@bryanmanuele/sessionless-authentication-using-jwts-with-node-express-passport-js-69b059e4b22c
======
Dirak
This article serves as a rebuttal to
[http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-
fo...](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-
sessions/). It deconstructs each criticism presented and explains why JWTs are
a secure and elegant solution to authentication. It also goes over how one
would go about implementing authentication securely using JWTs with Node +
Express + Passport.js.

~~~
chii
The biggest criticism from the original article is that you are unable to
revoke jwt individually. This was not debunked nor mentioned (unless I blind
and didn't see it, in which case I apologize).

~~~
nerdwaller
There’s nothing really stopping you from revoking a JWT individually - simply
keep the `jti` (or any arbitrary claim) in memcached/redis/etc and check it.
Obviously it’s no longer stateless and gives up some of the benefits of a JWT,
but it’s a solution if revocation is a business requirement.

Like everything, there’s no silver bullet (JWT vs random string token) -
business requirements dictate which makes sense.

~~~
xyzzy123
In system designs, have always kept “add revoked jtis to an expiring cache” in
the back pocket. Keeping in mind that it might be needed.

Turns out that just deleting JWTs from the client and letting them expire
naturally (10 mins) has always been good enough so far.

~~~
chii
The example from the criticism post cites the permission revocation issue,
which isn't solvable in jwt (without using serverside state, in which case you
negate the advantages of jwt).

making the expiration short works to some degree, but then you'd be forced to
constantly update the token.

As for deleting the jwt from the client - that's not trustworthy enough, since
the client controls themselves, you can't be sure that a deleted jwt is really
deleted!

~~~
xyzzy123
Ah sorry I think I need to be clearer with where I am coming from. Some of the
statements I’ve made rely on implementation decisions which are not universal
but I believe are common and well known in jwt based session designs.

Usually I work with web applications which have some server side state but
where bits are made stateless where sensible. So for example, user records
exist but we can save a db/redis call per request with stateless sessions.

To address your points:

It’s fairly easy to do jwt refresh (usually client driven with a timer) which
lets you keep individual jwt lifetimes short. The refresh endpoint can
sometimes be stateless.

This means that an inactive timeout happens by default but a hard limit on
maximum session lifetime (e.g. can refresh for up to 24h say) needs to be
implemented at the application level (you can also do this statelessly).

There’s design impact using stateless sessions but it’s usually positive in my
experience. When you ditch state in server side sessions, you have to figure
out where to put it. Take say, “last search filter” or something.
Traditionally you might have stored that in server side session storage,
deserializing on every request. Using JWTs you will tend to either offload
that to client JS or expose it as a “real” resource tied to the user record.

If you use public key signed sessions you can also decouple the “auth” part of
your app from the jwt consumers in a fairly principled way (e.g. in
microservices arch most services then don’t have the ability to issue
sessions, in fact your auth service can be in say its own aws account etc).

It’s not quite true that you negate all the benefit of using jwts with a
stateful “revocation” cache.

The key difference is that it is likely that the number of sessions actually
revoked in the last 10 minutes tends to be rather small compared to total
concurrent active sessions. This is faster and cheaper to store and search.

But 90% of the time you don’t actually need to build a revocation cache.

Usually there are two reasons to “revoke” a jwt in a webapp, the first would
be to do a “hard” user initiated logout. This means that the user is
explicitly asking for their session to be invalidated on the server side. The
second would be to allow an admin to terminate a specific user session.

Often when an admin locks a user out it’s better to actually implement that at
the level of the user record rather than mucking about with specific sessions.
Permission revocation also happens at the level of the user record.

In the logout case, the trust issue you mention is not an issue because the
client itself is requesting invalidation.

Generally the security difference between having the client simply delete its
copy of the jwt and actually doing hard invalidation on the server is fairly
minimal. May be a requirement for some projects though.

I think a lot of these “to jwt or not to jwt” posts suffer from all-or-nothing
thinking, real apps can pick and choose along a spectrum of options.

