6 ms·
I use stateful JWTs for session management, storing them in localStorage. If someone can exfiltrate the token, they will get a week long authorization, as well
by scandox 10y ago
I use stateful JWTs for session management, storing them in localStorage. If someone can exfiltrate the token, they will get a week long authorization, as well as some identifiable information (username, name and role).
Probably I can achieve the same overall system with cryptographically secure session cookies, that are persisted in a database, or other store that is accessible across multiple servers. I guess it would amount to the same thing.
Originally I implemented it because:
* My systems are SPA's. Totally JS dependent from the word go.
* I felt like there would be some advantages to being able to establish certain claims without verification. Say for display purposes prior to server comms (show a list of multiple available sessions for example)...In practise this hasn't really been true. Generally I find in the end I am always checking and verifying anyway - without any huge overhead.
* I've always had a sort of fuzz of uncertainty about Cookies. They always felt a bit out of my hands. Thinking it about rigorously of course, people can switch off JS. They can switch off persistence.
* All my user's local data can be persisted in one place, rather than having to store a reference in the Cookie and then lookup in localStorage. In reality though the code for this is pretty trivial...
So overall while I don't know how right he is, I feel like maybe he has a point. Why not just use cookies?
Maybe it's just because as a JS dev, I want everything to stay within a JS universe...and for some reason Cookies have always felt outside of that to me.
- Klathmon 10y agoIf I can offer some advice in the other direction, don't use cookies. I tried to do the right thing, use HTTP-only cookies set over an HTTPS endpoint only to find that it's stupidly complicated and has a lot of annoying edge cases. Turns out iOS's webviews don't like them, iOS in general doesn't like them to be on api.hostname.com if the app is on app.hostname.com, you can't validate if you are logged in or not without doing a web request (which is annoying as hell if you are trying to keep a "logged in" state in something like a react app), you need to deal with a bunch of stupid flags to get the damn browser to even let them go across domains, and a hell of a lot of other annoyances that I can't remember right now. We are most likely moving to something like JWTs (stored in localstorage or indexeddb) soon because of these issues.
- yarper 10y agoIdeally you need to use httpOnly cookies to store your JWTs too.
- zimbatm 10y agoIf the SPA is doing XHR requests then a localStorage is also an option. It has the advantage that the application can control on which requests the token is being sent, in contracts with cookies where they are sent for any requests on then domain.
- cptskippy 10y agoWouldn't you need to assign your cookies to the TLD for them to be accessible to both subdomains?
- Klathmon 10y agoWe only wanted them assigned to the subdomain that needed them (api.hostname.com), and we set it up that way to make sure we wouldn't accidentally expose cookies to other domains down the line.
- zeveb 10y agoI think you should probably have used another common parent domain, like app.web.hostname.com & api.web.hostname.com, with the cookies set for *.web.hostname.com (or something).
- zimbatm 10y agoIt would also send them to the CDN if it's hosted on a cdn. subdomain.
- cptskippy 10y agoDefinitely, there's a whole host of potential pitfalls from assigning cookies to the TLD. From the OP's post though it sounded like their issue was one subdomain being unable to access cookies of another subdomain.
- lobo_tuerto 10y agoAnother advice: You shouldn't be saving the JWT on localStorage for security reasons, have a look at the info here: https://news.ycombinator.com/item?id=13866965 https://news.ycombinator.com/item?id=13866965
- scandox 10y agoIndeed the article in question links here as required prior reading: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo... So my comment was in the context of having read both of these. In the link here he also strongly argues against storage of JWT in localStorage.
- throwaway2016a 10y ago> So overall while I don't know how right he is, I feel like maybe he has a point. Why not just use cookies? Because in a highly distributed system hitting a database to validate authorization is expensive and causes bottlenecks. A cookie that requires you to hit the database does not solve that issue. Although if the cookie was signed some way that can be cryptographically verified then great. But then you are essentially re-implementing something you could be doing in a standard way instead.
- falcolas 10y ago> Because in a highly distributed system hitting a database to validate authorization is expensive and causes bottlenecks. Don't you have to do something similar to invalidate tokens anyway?
- devdoomari 10y agoyou can use refresh-token to get 'access token' at https://site.com/access-token https://site.com/access-token, and then use access token for API access. Then, having the 'just-the-right-amount-of-short-expiration-time' for access token helps... maybe? :)
- throwaway2016a 10y ago> Don't you have to do something similar to invalidate tokens anyway? Not exactly.. 1. Invalidation lists can be held in memory easier than an entire token database. And if the invalidation list is huge you can distribute a bloom filter across your nodes and use that to check before hitting the database. 2. As another poster pointed out. Bearer JWT tokens are meant to be short lived. If your implementation is ontop of OAuth use a longer lived refresh token to get a new bearer token every so often (say half an hour). So if you are OK with your invalidated tokens being OK for "up to" the expiry (so up to half an hour in this example) you only need to do strong validation on the refresh tokens.
- pilif 10y agocookies have one advantage over localStorage and custom headers though: They can be set by the server in a way that client-side JS code doesn't get to see or change them. This makes abusing XSS vulnerabilities to get to the token slightly harder.