DEV Community

Cover image for How JWTs Could Be Dangerous and Its Alternatives

How JWTs Could Be Dangerous and Its Alternatives

Pragati Verma on December 04, 2022

Introduction JSON Web Tokens (JWTs) are the most popularly used tokens for web authentication and managing user sessions in modern-day s...
Collapse
 
dagnelies profile image
Arnaud Dagnelies • Edited

I don't really understand the attention this triggers. If you want a session, just use a (http-only cookie), that's super simple, secure, etc. Cookie is set, you're logged in, cookie is cleared, you are logged out. It cannot be simpler and is the traditional way of managing sessions. It works perfectly.

That said, JWTs are great and super useful, just not as a replacement for user sessions! JWTs are basically most useful for other things: "authorization" to use some third party API on behalf of the user, internal communication between your own services and mostly in the OAuth2/OpenID flow. This basically just requests a JWT to fetch the user's profile email from the identity provider.

Last but not least, you can also put a JWT as http-only cookie to validate a user session without DB lookup. That way, it cannot be "stolen" and clearing the token is sufficient to "logout" the user.

Collapse
 
ayankumarsaha profile image
Ayan Kumar Saha

My experience with cookies is not so good. If the end user is using browsers like "brave" which by default blocks cookies or using some sort of cookie-blocking browser plugin then the whole cookie-based session management will not work properly.

Collapse
 
cosinus30 profile image
cosinus30

It seems default behaviour of brave is not to block all cookies, but to block 3rd party cookies. Unless user disables all cookies (which is not recommended by the brave team) http only cookies will work just fine.

Collapse
 
josethz00 profile image
José Thomaz

I agree with you, but if your client is a mobile app, you might have to think a little bit more, because cookies can be hard to handle in mobile apps

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Hi. There's a much simpler and efficient way to invalidate tokens. I guess I can make a little article explaining. Stay tuned. Since it is probably a small topic I'll most likely have it out by end of day.

Collapse
 
ankit9761 profile image
Ankit Kanyal

Wow great article thanks for sharing the info

Collapse
 
cosinus30 profile image
cosinus30

What I do not understand is how JWTs suffer from man in the middle attacks. If the data is sent through secure channels (HTTPS) man in the middle should not be able to retrieve the data from the encrypted data, right?

Collapse
 
phlash profile image
Phil Ashby

Thank you for the detailed description of JWTs, and for noting the design consideration that they will continue to work for the expiry period (unless revoked in some way).

TL;DR - it depends, look at your wider business risks and choose technologies that minimize total risk.

As with all security issues - this is a risk balance, usually trading complexity/cost of distributed caches (eg: Redis) and database performance against the possible outcomes of a token being valid for <n> minutes. In federated business relationships (ie: those 'log in with Google' buttons), JWTs are often an essential part of the larger OpenID Connect protocol in use.

If (as in your example) your business is not federated, is critically dependant on rapid session revocation and performs database transactions on most requests, then retaining user authentication in the database makes sense. If your application doesn't make many database transactions, then it may be more cost efficient (at the risk of increasing complexity) to introduce a cache like Redis, to limit the performance needs of the database.

I would also ask 'would a problematic user be identified within the token expiry period', and 'whats the worst that could happen'? There may now be humans in the loop, eg: support teams discussing user reports, investigating posts, etc. and taking several minutes before a decision to block/ban a user is taken - likely longer than their current token expiry?

Finally, there are network mitigation measures that can be applied, such as rate limiting, or IP blocking, to limit impact.

Collapse
 
darjanbogdan profile image
Darjan Bogdan • Edited

JWT is just a format, a way to transfer *insensitive * data (thus not encrypted, but signed) that uniquely identifies a party (client, user) that issues request to the server. The security doesn't lie in the token itself, the security is ensured by complying to auth protocols (e.g. OAuth2, OpenID, ...) that are being used by both clients (gets a token) and servers (validates and uses).

Having said that, JWT indeed could impose a security risk since they have expiration (not self-destruction), and if some bad guy gets in hands valid/non-expired token it can effectively impersonate client and possibly user.

So, in cases when zero-trust client device is connecting to the server, JWT formatted tokens (and all other self-contained tokens) is not suitable, but so called "reference" tokens are issued by authorization/identity servers instead. Usually, validation of such tokens is implemented following OAuth 2.0 Token Introspection method described in RFC 7662. This effectively gives possibility to on-demand revoke any token in case of compromises.

In security world, personal devices which includes laptops, phones and desktops are considered safe enough to use JWT, thus you can see a wide spread adoption across the browsers and applications. In IoT world, you will almost never see JWT usage, due to inherently unsafe environment in which such devices usually work.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

I promised, so I delivered. Here's a much simpler and more effective way of invalidating tokens.

Collapse
 
kostyatretyak profile image
Костя Третяк • Edited

Sometimes a couple of tokens are used - refresh and access token. Access token has a lifetime of only a few minutes. Instead, the refresh token can have a lifetime of months. The additional advantage is that each of these tokens are works with different servers.

With such a scheme, the authentication/authorization server is accessed only with a login and password, or with a refresh token. And the resource server deals only with the access token.

If there is a need to remove access for a specific user, the maximum time during which he will still have access to prohibited resources will be equal to the lifetime of the access token (ie, a couple of minutes). After the access token expires, this user will be forced to contact the authorization server with a refresh token, but he will be denied access token renewal.

If in a specific case instant revocation of access rights is important, and even a few minutes will be critical, then the gain from JWT is really leveled off, and you will have to go to the database for each request. Apparently, such a scenario is quite rare.

Collapse
 
szalonna profile image
Joe

My understanding is that the original idea for JWT was to create sg which can be used on a controlled environment, like between microservices. But as soon as the token moves out from this safe zone, you should consider using a standard session management on the public entry points and map the user requests to short lifespan tokens.

Collapse
 
ecki profile image
Bernd

Assuming token revocations are seldom you can use a generational approach: you don’t care about expired tokens, but if you revoke a valid one you will have to sent it’s Id to a fast lookup (db or redis) and in addition update the generational threshold on all policy enforcement points (servers). This can be done with a cache invalidation publish token or a cache hoerwchy. „All tokens below Generation number x now need an additional lookup roundtrip“. Since all new tokens have a newer generation number (or minimum issue timestamp) those won’t be looked up in the cache until somebody inserts a new revocation. If you expect very seldom revocation you can instead broadcast the IDs or the revoked userId.

And just to mention some auth. systems combine JWT it’s callbacks to validate the key or request analysis data. For example in OIC. In that Case the callback can also check revocation.

BTW JOSE also supports encrypted tokens, if you use a authenticated encryption it can even double as a validation. However this would require a pairwise shared secret. In some cases where this is not wanted you would encrypt a signed token.

Collapse
 
rcerljenko profile image
Ricardo Čerljenko

Hi,,

As an alternative I can add the "PASETO" implementation which is kinda like a JWT 2.0 targeting all its defects...

paseto.io

Collapse
 
tinkerbaj profile image
tinkerbaj

Exactly so secure

Collapse
 
webjose profile image
José Pablo Ramírez Vargas
Collapse
 
wadecodez profile image
Wade Zimmerman

IMO JWT is only good for signed requests, ie not authentication or authorization, but just checking that the data was not tampered with.

Collapse
 
nigel447 profile image
nigel447

like how we often create a signed(checksum) url where the jwt is superior to the signed url in that we have the ability to encrypt the attributes and also standardize the encoding

Collapse
 
damianreloaded profile image
Info Comment hidden by post author - thread only accessible via permalink
DamianReloaded

This is a verbatim copy of this article:

redis.com/blog/json-web-tokens-jwt...

Collapse
 
avi_haa profile image
Avi haa

OAuth2, Passport, Spring Security, Auth0, and Keycloak are the most popular alternatives and competitors to JSON Web Token.

Collapse
 
liq profile image
Bernad Delic

Your point is wrong: JWT tokens can be invalidated after logout. You can have a dedicated table or some other kind of storage to store blacklisted tokens.

Collapse
 
leober_ramos33 profile image
Leober Ramos • Edited

Yeah, but that is not "revoking" the token as such, revoking is that the token as such should no longer work.

Still, she explains below that you can have a separate table to store "revoked" or expired tokens in, and make a request to the database on each request to check if that token hasn't been revoked, but that a fails of performance if your table has a lot of records (which is common as it is an expired tokens table).

Although databases are getting faster these days, and if you have optimized your server, your application, you have caching and a CDN in place, that millisecond optimization of that extra DB call is only for applications that need to run at speed. of light, for example, Facebook should have something similar.

Collapse
 
lovepreetsingh profile image
Lovepreet Singh

📍 Good One. Helpful. Kindly check my BLog too at dev.to/lovepreetsingh/make-thousan...

Some comments have been hidden by the post's author - find out more