Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Every time I want to use a JWT, it seems like it's the suboptimal choice, so I've never found a genuine use case for them.

Most recently, I wanted to implement 2FA w/ TOTP. I figure I'll use 1 cookie for the session, and another cookie as a TOTP bypass. If the user doesn't have a 2FA bypass cookie, then they have to complete the 2FA challenge. Great, so user submits username & password like normal, if they pass but don't have the bypass cookie the server sends back a JWT with 10 minute expiry. They have to send back the JWT along with OTP to complete the login.

I figure this is OK, but not optimal. Worst case, hacker does not submit any username/password but attempts to forge the JWT along with OTP. User ID is in clear text in the JWT, but the key only exists on the server so it's very difficult to crack. Nevertheless, clients have unlimited attempts because JWT is stateless and they can keep extending the expiry or set it to far future as desired. Still, 256 bits, not likely they'll ever succeed, but I should probably be alerted to what's going on.

Alternative? Create a 2FA challenge key that's unique after every successful username/password combo. User submits challenge key along with OTP. Same 256 bit security, but unique for each login attempt instead of using global HMAC key. Also, now it's very easy to limit attempts to ~3 and I have a record of any such hacking attempt. Seems strictly better. Storage is not really a concern because worse case I can still prune all keys older than 10 minutes. Downside I guess is I still have to hit my DB, but it's a very efficient query and I can always move to a key-value store if it becomes a bottleneck.

I don't know, what's the use-case? Server-server interaction? Then they still need to share a key to validate the JWT. And probably all but the user-facing server doesn't need to be exposed to public internet anyway so why the hoopla adding JWT? I haven't looked into it much because I don't believe in this microservice architecture either, but if I were to go down that road I'd probably try gRPC/protobufs and still not bother with JWT.



A JWT can include claims - that's the difference: JWTs are a bit more complicated data structure out of the box. You can do authN and authZ in one go.

You can do it all via individual browser cookies but it will be complicated. However you can dump session cookies to a database and then you can do claims locally on the server and use that cookie to tie it all together.

So I think you can do it either way.

JWTs are mutually authenticated (shared secret) but cookies are not.


Everything can include "claims". Claims are just fields in a JSON object. If you're using your own token format which is based on Libsodium's secret box, you can just do `secretbox_seal(secret_key, json_encode(claims))`. It's a no-brainer one liner. You can even use MessagePack or protocol buffers instead of JSON and save a little bit on the token size.

JWT might do other things for you, like standardizing how to deal with key rotation (using the "kid" claim and JWKs discovery urls), or tying a bearer token to a PoP structure (DPoP), but that's all about standardization. And as a standard JWT is too flexible and ambiguous. There are better proposed standards out there, and for most of the thing JWT is used for (non-interoperable access tokens) it's an overkill.


> what's the use-case?

The use-case I always remember people presenting for JWTs was mostly part of the "serverless" fad/hype.

The theory was presented like this: If you use a JWT your application logic can be stateless when it comes to authentication; So you don't need to load user info from a session database/kv store, it's right there in the request...

The only way that makes any sense to me, is if your application has zero storage of its own: it's all remote APIs/services, including your authentication source. I'm sure there are some applications like that, but I find it hard to believe that's how/why it's used most of the time.

Never underestimate this industry's ability to get obsessed with the new shiny.

I had an eye opening experience many years ago with a junior dev (I was significantly more experienced than he was then, but wouldn't have called myself "senior" at the time).

He had written an internal tool for the agency we both worked for/through. I don't recall the exact specifics, but I remember the accountant was involved somewhat, and it was a fairly basic CRUD-y PHP/MySQL app. Nothing to write home about, but it worked fine.

At some point he had an issue getting his php/mysql environment configured (I guess on a new laptop?) - this was before the time of Docker; Vagrant was likely already a thing but he wasn't using it.

From what he explained afterwards I believe it was just the extremely common issue that connecting to "localhost" causes the mysql client to attempt a socket connection, and the default socket location provided in php isn't always correct.

As I said, I heard about this after he'd decided that connection issue (with an app that had already been working well enough to show off to powers-that-be and get approval to spend more paid time on it) was enough to warrant re-writing the entire thing to use MongoDB.

As I said: never underestimate this industry's ability to get obsessed with the new shiny.


Long before JWT existed, if you wanted to pass some trusted data through an untrusted channel, you would make a payload with an expiry, encrypt or sign it with your secret key, then send it. However, you would need to make up your own way to send this info. For example, if this were a website, you might dump the signed/encrypted payload into several form fields and upon receiving it back, you would verify that it was signed with your key.

Now that JWT exists, there is a standard way to do it so you don’t have to write the same boring code a bunch of times in different languages. You just have one string you pass in one field and if you tell someone else that it’s a JWT, they know how to parse it. You don’t have to document your own special way anymore.

At the end of the day, it’s just a standard for that specific problem that didn’t have a standard solution before. If passing data like that is not a problem for your use case, then you don’t need the tool.

To use your Protobuf example, there was a time before Protobuf or tools like it existed. I can tell you that writing the exact same protocol code by hand in Java, PHP, and Python is absolute tedious work. But if it never came up that you had to write your own protocol, you neither know the pain of doing it manually nor the pleasure of using Protobuf, and that’s fine.


The issue with JWTs is that it is very often misused standard


> I don't know, what's the use-case? Server-server interaction? Then they still need to share a key to validate the JWT. And probably all but the user-facing server doesn't need to be exposed to public internet anyway so why the hoopla adding JWT?

JWTs across servers are typically used with signatures, not in HMAC mode (so no globally shared HMAC keys). Then the issuer simply exposes a JWKS endpoint for downstream consumers (so no additional maintenance to distribute public keys).


I use JWTs to let me do auth on cached resources. I can verify permissions in an edge worker and deliver the cached resource without needing to roundtrip to the database. Not sure how to implement that without JWT (or rolling my own solution). Lots of people here saying some version of “I don’t see the use case, just use X”, but these kinds of standards nearly always arise as a result of a valid use case, even if they aren’t as common.


In your scenario you could still apply additional protections to a user id after detecting X attempts of sending a forged JWT. At least you could alert on JWTs that arrive with invalid signatures. Or you could put a 2FA challenge key inside the JWT, just use the JWT as a container to hold the information you would have shared with the client anyway.

I agree that JWTs don't really do anything more than a cookie couldn't already do, but I think the use case is for apps, not web browsers. In particular apps that do raw HTTP API calls and do not implement a cookie jar. And then because most companies do "app first development", we end up having to support JWT in the web browser too, manually putting it into localstorage or the application state, instead of just leveraging the cookie jar that was already there.

We just recently had to implement an SSO solution using JWT because the platform only gave out JWTs, so we ended up putting the JWT inside an encrypted HttpOnly cookie. Seemed a bit like a hat-on-a-hat, but eh.


> we end up having to support JWT in the web browser too, manually putting it into localstorage or the application state, instead of just leveraging the cookie jar that was already there.

> We just recently had to implement an SSO solution using JWT because the platform only gave out JWTs, so we ended up putting the JWT inside an encrypted HttpOnly cookie. Seemed a bit like a hat-on-a-hat, but eh.

Why would you think that? Cookies are a perfectly normal place to store JWTs for web applications. If your frontend is server-side-generated, the browser needs to authenticate the very first request it sends to the server and can't rely on anything apart from cookies anyway.


There is a jti claim that can be used for storing a token ID, so you could enforce tracking all issued tokens server side.

Cracking 256bit by brute force is unrealistically unlikely as you said, and there are many systems that could be compromised by that compute, an isolated jwt sig seems like just a very specific example.

A nice benefit of JWT for me is that it can be asymm signed and verified (ID tokens)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: