Hacker News new | ask | show | jobs
by angoragoats 5 days ago
> Another point is that managing session data on the server-side is a pain... If your app server goes down, stale session data would be left behind in your session store; it can easily become orphaned... So you need to set an expiry on it to ensure that it will be cleaned up no matter what... But you need to keep extending the expiry while the user is still online. God forbid you create the session data before you set the expiry on it and the operation that sets the expiry fails (e.g. server crashes at the precise moment or some error occurs which causes it to be skipped)... In practice, it's hard to avoid stale/orphaned session data.

Tell me you haven’t been writing web apps for a long time without telling me. There are many ways to solve the problems you describe here, which have been put into widespread use by web frameworks serving literally billions of users stretching back decades. Why reinvent the wheel with something that wasn’t designed to be a long-lived session store in the first place?

I think the Rails default is quite clever (the entire session lives in a cookie on the client), which gets around most of the problems you specify. But there are many other approaches if that doesn’t work for your use case.

1 comments

My point and previous commenter's point was more about managing the session data, not the session ID itself.

You're right that now it seems a lot of these session stores like Redis have improved. It seems they now enforce TTL and even provide sliding TTL on read. I haven't touched on this feature in a while but it used to be a major pain before.

These niceties add overhead behind the scenes but manageable... But IMO, it still falls short of the simplicity of just checking a JWT signature. In many situations, the revocation list would be relatively short compared to the number of sessions; it's a lot easier to manage... Also, critically, it's not a Single Point of Failure because the system will keep servicing users even if the revocation list is down... It just won't be able to ban users until it comes back up. This is usually a lesser concern.

> My point and previous commenter's point was more about managing the session data, not the session ID itself.

Yes, I understood that clearly, and it seems that maybe you didn’t understand my post.

In Rails, by default, the session data itself (not an ID) lives entirely in a cookie. No server-side session management logic of any kind is enabled or necessary.

Are there situations where this isn’t the right fit? Of course. But this is one of many solutions that have been in place for decades that don’t involve using a token that is intended for short-lived and/or one-time claims.

Edit: I had a vague memory of having a very similar conversation before on HN, and it turns out it was with you. Feel free to re-read if you’d like a little more context into why I think you’re using JWTs in a way that is, at minimum, not what they were designed for:

https://news.ycombinator.com/item?id=40496378

Haha seems you have found your arch-nemesis ;p

I wasn't familiar with the RoR implementation. We may have been talking past each other. I'm thinking about it from an access control PoV.

There are alternatives to JWT which work on the same principle but personally I haven't found any reason to move off a well established and popular format to some unknown format whose drawbacks aren't as well understood or which limits interoperability.

I checked with Claude. It seems that RoR's default is in fact its own custom implementation of a similar mechanism but with encryption instead of just signatures. This is a good approach if you want to store secret data in the session but personally I only store non-sensitive info and I prefer using JWT HS256 which is fast/cheap compared to full encryption. I try to keep my signed data light, especially if it has to be sent over the wire frequently.

I find the JWT approach more minimalist; it's only for determining account ID and privilege level, nothing else and it doesn't have to be secret. I feel like storing anything more than the bare minimum required to determine access to resources is overkill.

> There are alternatives to JWT which work on the same principle

My general position is that JWTs are not well-suited or designed for web app session management, full stop. There are direct alternatives to JWTs like PASETO and Macaroons, and I don't think those are suited for session management either (though in general they are better designed from a security and simplicity perspective).

> RoR's default is in fact its own custom implementation of a similar mechanism but with encryption instead of just signatures

That's pretty much correct, with the caveat that you don't need to add a bunch of machinery with footguns galore on the frontend and backend just to be able to parse them. And as I pointed out in our last discussion, this has been the default session storage mechanism in Rails since years before JWTs existed.

> I prefer using JWT HS256 which is fast/cheap compared to full encryption

This feels like like bike-shedding for all but the largest of apps.

> I try to keep my signed data light, especially if it has to be sent over the wire frequently.

Yes, this is a recommendation for Rails' default session mechanism as well, since most browsers impose a fairly small size limit on cookies (4KiB IIRC).

> I find the JWT approach more minimalist; it's only for determining account ID and privilege level, nothing else and it doesn't have to be secret. I feel like storing anything more than the bare minimum required to determine access to resources is overkill.

There are a lot of other use cases for session data, especially if you're using a full-stack web framework vs. a SPA with a separate backend (I have strong opinions on this as well, but that's a different discussion). For example, Rails has the concept of a "flash" where you can display temporary, ephemeral messages to the user. These are stored in the session, consumed on the next request the browser makes, and then removed.