14 ms·
JSON Web Tokens vs. Sessions
- mkagenius 10y agoA security note regarding JWTs - https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ https://auth0.com/blog/2015/03/31/critical-vulnerabilities-i...
- lobster_johnson 10y agoThat one is from March 2015, and are about some specific libraries that had vulnerabilities at that time.
- jordz 10y agoAlso, worth mentioning this article as an opinion: 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... Edit: Title is Stop using JWT for sessions
- dang 10y agohttps://news.ycombinator.com/item?id=11895440 https://news.ycombinator.com/item?id=11895440
- hanswesterbeek 10y agoThat article is really good.
- smaili 10y agoCorrect me if I'm wrong but the benefits sound very similar to a good old fashion cookie except that you're not limited by 4kb.
- harikb 10y agoRight, but then the browser is automatically doing the job for you (saving the cookie and then returning in the next request). That would be so bad! We can't do custom code to acheive the same thing...
- Negative1 10y agoThis is the common misconception. Think of a cookie as a storage 'bucket' on a user's device. It can store up to 4KB in bytes of, well, anything (a string). JWT is format. That's it. It is enciphered and has the ability to store JSON, but otherwise, it's just a format or scheme that allows you to organize how you store your session (or whatever) data. As an example, in my usage I actually store my JWT in a user cookie and all it keeps is the expiration, user id and a few other tidbits I don't want to hit a database for but am comfortable exposing in case the token is cracked.
- mkagenius 10y ago> but am comfortable exposing in case the token is cracked. If the token is cracked, it is essentially the account compromise. You probably meant the base64 decode if the token is 'leaked'?
- ekryski 10y agoI agree that's how we treat them with Feathers. You may know this already but JWT's are intended to be decrypted on the client so you shouldn't be be saying "if" it is cracked, more "when". The signature is only good for ensuring that the content hasn't been manipulated. Not that you are, but for others, never store anything inside a JWT that is sensitive, and if it is make sure you encrypt it first before you put it in the JWT payload.
- carsongross 10y agoI recently added support for reading/writing localStorage variables in intercooler.js to support things like this: https://github.com/LeadDyno/intercooler-js/commit/e83a1ff76a5c3d9c97c2bb63ee707eda1b100496 https://github.com/LeadDyno/intercooler-js/commit/e83a1ff76a...
- tootie 10y agoIf you need to validate the Authorization header on every request that's not really different than using session tokens we've been using for the past 15 years. JWT is just a formalized way of managing cookies. Which is nice and I like it, but it doesn't actually enable anything that couldn't be done before albeit with a more ad hoc approach.
- aleem 10y agoRight, Signed Cookies. JWT doesn't make the claim that it's a new concept, you are assuming as much. It's a standard and as you correctly gleaned and like most other standards, comes with a lot of benefits, best practices, is battle tested and ready-to-use in your favorite frameworks. It becomes even more useful if you application serves multiple clients such as browsers, iOS applications and so forth because you can hit the ground running without having to reinvent anything.
- zatkin 10y agoAren't cookies the safest approach for storing authorization tokens? I recently found out that both Google and Facebook use cookies for authorization, so it seems like the way to go, though I've read that it gives programmer headaches.
- scope 10y agoCookies can be/are used for extensive tracking (even when you're not techically on the site). The EU requires websites that use cookies to display conformation message on how cookies will be used to track the user.
- arianvanp 10y agothe EU requires websites that use _any_ kind of local storage to display a conformation message on how the storage will be used to track the user. It is not specific to cookies.
- spriggan3 10y agoThe infamous "cookie" law isn't limited to Cookies. JWT, local storage and co all fall under the same law that will force you to put a disclaimer on your webpages. There is absolutely no difference between the 2 in that regard. The fact that you think otherwise is a serious legal risk for your business if you have one.
- nstart 10y agoThat last part where he talks about logging out being the responsibility of the client is rather key. Basically I can't invalidate the key from the server side. So if a user's account is compromised and they recover it on their mobile app for example, I can't sign the user out of everywhere else too. It's what has given me pause about jwt so far and has held me back from using it. I find the cookie is generally good enough to hold most other information I need about the user.
- aleem 10y agoThe impact can be mitigated by having low TTLs and using refresh tokens. This will give you a rolling window. If the TTL is 10 minutes and the client doesn't make any requests in 10 minutes, they will be timed out. But if the client continues to have at least one request every 10 minutes the session persist. Session persistence can also be ensured by having your web-client for example make a request to the server every couple of minutes. Server-side key invalidation is entirely possible but it would require having a blacklist of disabled keys and comparing every requests against the black list. This would obviously concede the benefits of scale from JWT tokens since you are doing the same thing as server side sessions. However, the black list should be considered only as an escape hatch and need not be enabled at all times. In fact, once all the tokens in the black list expire, the black list itself can be disabled and things go back to the way they were.
- btdiehr 10y agoWhy do you think you can't invalidate a JWT? Store a JWT that is associated with some object in a database that has the field `isInvalidated`. This isn't rocket science. Sure - this turns the JWT token into a session but there is no way to invalidate based on something that isn't determined at creation time without storing something in a database.
- jontro 10y agoWhat's the point of using a JWT if so? This effectively converts it into a session token
- StevePerkins 10y agoFor people using JWT as a substitute for stateful sessions, how do you handle renewal (or revocation)? With a traditional session, the token is set to expire after some period of inactivity (e.g. one hour). Subsequent requests push out the expiration... so that it's always one hour from the last activity, rather than one hour from initial authentication. With JWT, the expiration time is baked into the token and seems effectively immutable. To extend the session, you have to either: 1. Re-authenticate from the browser every hour and store a new JWT token, which is kind of an awful user experience, or 2. Renew the JWT token from the server side every hour. At least in Google's implementation, this requires the user to grant "offline access" (another awful user experience)... and you'd need some hacky approach for replacing the JWT token in the user's browser. So with all the recent discussion about not using JWT for sessions, what do you guys do? Do you simply make users re-authenticate every hour? Is there another magic trick that no one has brought up? In my own shop, we're using the browser's JWT token as a server-side cache key... and storing the "real" expiration in cache so that it can be extended (or revoked) as needed. I would be interested to know if others take a similar approach, or have issues with that?
- darksaints 10y agoWith JWT, you have the option of stateful or stateless. Stateless gives you cheap federation (any server can authenticate a token issued by another server), but you lose the ability to handle revocation without some sort of statefulness introduced (a redis cache with revoked token ids for example). Stateful is basically a non-cookie based session. One possible alternative to enable auto-renewal is to issue a new token with every request, and manually bake in the persistence of the token into your front end client. In my own system, I have login with facebook, which submits current FB auth tokens with every request, after which I issue my own app token with all the necessary authorization information for my business logic. Whenever the app token expires, I attempt re-authentication using facebook login, and if successful I send back an updated app token. The front end client has logic built in to compare and swap app tokens if they change and persist in sessionStorage. It's pretty hacky. I'm a little worried about vulnerabilities that I might be introducing. I luck out in that I don't have a public API which would force the client to implement my front end logic. But it works, for now.
- saynsedit 10y ago[headerB64, payloadB64, signatureB64] = jwt.split('.'); if (atob(signatureB64) === signatureCreatingFunction(headerB64 + '.' + payloadB64) { // good } else // no good } You really need a constant time compare for the signature, else you leak information about the correct signature in the timing of the response.
- jsmeaton 10y agoI don't think this is true. Timing attacks are only really useful if you can change a single piece of data and analyze the time difference until you find the right value, over and over again. Like comparing a password. The unknown data in the signature creating function is a key. The output is a hash. If you were trying to capture the key you would need to guess what the key was to get the correct hash. Each byte you change results in a cascade of changes in the output. You can't get information about the key from a timing attack on a hash function. I think.
- saynsedit 10y agoThis is not about retrieving the key, an attacker can still retrieve the correct opaque signature for specific data. This potentially allows an attacker to impersonate a user.
- jsmeaton 10y agoThe signature is already available - it's literally appended to the output. Verifying the signature is done by hashing the body with a secret (key) and comparing it to the known signature. "Known" === HMACSHA256(payload, secret) You already know the left hand side. How would a constant time comparison protect you from a timing attack in this scenario? It wouldn't. The signature is known, the payload is known, but the secret is not known. That means you'd have to attack the secret, which you could even do offline. By iteratively changing the secret, even if you were to get the first half of the hash right, the next character you change would potentially change every single character in the output. JWT/JWS does not concern itself with keeping the token secret or providing encryption. It's only concern is message authentication. If you leak your token, someone else can impersonate you, just like if you'd leaked your session cookie. The only viable attack on the scheme is to brute force (or discover) the secret, which would allow you to sign a message of your choosing. Once you can sign a message as if you were the server, then you may impersonate anyone you choose.
- Bino 10y agoWhy the obsession with 3 letter short names? Why "typ" and not "type". I'm sore the overhead can be ignored and the parser doesn't care.
- ninkendo 10y agoThe JWT has to fit inside HTTP headers, which means it's not unlimited in size. The default header size limit varies by web server, but once you get above 8k it becomes a game of "which reverse proxy is choking on these headers this time?". It's compounded by the fact that a lot of web servers (ie. nginx) have a global header size that limits all of your headers together, not just any one header, which means your JWT size limit is nondeterministic, especially if have large-ish cookies in your request. There's standard ways to include the JWT in the request body, like form encoding, but that doesn't work for GET requests, so in practice everyone uses the Authorization header.
- wtbob 10y ago> There's standard ways to include the JWT in the request body, like form encoding, but that doesn't work for GET requests, so in practice everyone uses the Authorization header. You can include a JWT as an access_token URL parameter, which works in a GET: https://foo.invalid/bar?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- tszming 10y agoPeople don't realize it is not a proper comparison as JWT is only the format/spec - you can still achieve stateless client session by encrypting an XML payload (e.g. user id) in the browser cookie. Storing data in client and verify by signature is not a new thing.
- moyok 10y agoThe thing that scares me about using JWT is that all security completely relies on the one secret that is used to sign tokens - any person with access to that secret has got potentially unlimited access to the app. They can now impersonate any user and do basically anything.
- wtbob 10y agoYes, it'd be better if JWTs were full-fledged certificates, where ultimate authority could be confined to some offline key, who delegates authority for strictly delimited period to online keys. Or ultimate authority could belong to k out of a collection of n keys: one would need to suborn k keys to suborn the authority as a whole. RFCs 2692 & 2693 specify a really great, lightweight, way to do that. They resulting certificates needn't be a whole lot heavier than a JWT, and are much lighter-weight than and X.509 certificate. The RFCs also specify an intelligent, domain-neutral algorithm for performing calculations on tags (what JWT refers to as 'claims') and keys. It's a pretty awesome solution, and there are a lot of good ideas in there. A streamlined version could, I think, end up being competitive with JWTs.
- iheartmemcache 10y agoSPKI was deprecated for SDSI[1] (also done by Rivest), both of which AFAIK haven't been touched in ~20 years (which is fine by me, if the theory and implementation are solid, but SDSI has CORBA/J2EE smells all over the RFC from what I remember. Lightweight, eh...) [1] https://people.csail.mit.edu/rivest/sdsi11.html https://people.csail.mit.edu/rivest/sdsi11.html
- wtbob 10y ago> SPKI was deprecated for SDSI No, it's the other way around: SDSI was deprecated for SPKI, which took a lot of its ideas about naming from SDSI. > both of which AFAIK haven't been touched in ~20 years (which is fine by me, if the theory and implementation are solid, but SDSI has CORBA/J2EE smells all over the RFC from what I remember. Lightweight, eh...) SPKI is indeed old, but the fundamental ideas are really good, and some of them (the cert calculus) are timeless. It needs a v2.0 to update the recommended crypto, specify some more use cases and so forth. But it's really, _really_ good, far better than XPKI and extremely capable. And still pretty lightweight.
- hharnisch 10y agoJWT is especially useful for validating requests in a microservice architecture. You can pass around the token an embed roles in them. No need to keep a session store with them!
- hharnisch 10y agoOn another note I've been working on a service that generates expirable/refreshable JWTs. Its a good way to start trying them out https://github.com/hharnisc/auth-service https://github.com/hharnisc/auth-service
- joepie91_ 10y agoBetter remove that again. It is extremely dangerous to store any kind of credential in Local Storage. Cookies are the (only) correct place for storing credentials.
- areed 10y agoBecause you can set Secure and HttpOnly flags on cookies? This merely brings them up to the same level of security you get with Local Storage. http://blog.portswigger.net/2016/05/web-storage-lesser-evil-for-session.html http://blog.portswigger.net/2016/05/web-storage-lesser-evil-...
- pags 10y agoWhat is a "level" of security? If I'm able to inject arbitrary code into your page, with it I can access your local storage data, but I can't access your "http only" cookies - so there's at least some "level" of difference.
- garfij 10y agoIf you're at the point where someone can inject random code into your site, you've already lost and have so many more problems than access to localStorage.
- palmdeezy 10y agoThis is the 3rd or 4th article in the last 3 weeks on JWT. Each has argued that JWT is either secure or totally useless. What is the deal?
- joepie91_ 10y agoThe two are not mutually exclusive. Either way, my article (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...) argues neither.
- DenisM 10y agoIIRC tptacek has been beating this drum for a while, but it seems that he got tired of it, so I should pick the drum sticks in his stead: Use less crypto. The less crypto is being used, the fewer mistakes are being made. When it comes to sessions, generated a secure random 256 bit token and use that as a session id. Store it in a database or in-memory store. Sticky sessions + local session token storage will fix your network latency problems when you start scaling out. Federation becomes moderately difficult. Perhaps you could store a copy of session id on each node, and when a session id is compromised, proactively reach to all nodes and ask them to purge the session. This allows immediate mitigation for a session id leak, and since it doesn't rely on timeouts there is no vulnerability window for data exfiltratiin upon a breach. And no crypto.
- nbarbettini 10y ago> The less crypto is being used, the fewer mistakes are being made. I don't understand this position. What do you mean by "fewer mistakes are being made"?
- joepie91_ 10y agoCryptography-related code is incredibly easy to fuck up, and the tiniest mistake can completely break your security model. A mistake that could be insignificant in other kinds of code, could easily be critical in crypto-related code. Thus, you reduce both the amount of mistakes and the impact of mistakes by avoiding crypto where possible. EDIT: Yes, this includes using existing libraries. It's not just the implementation of the primitives themselves where issues occur.
- girvo 10y agoIn fact, a heap of JWT libraries had massive vulnerabilities in them not that long ago, that mean you could easily forge JWTs.
- atombender 10y agoThis misses one huge benefit of JWTs: Other parties can trust your token if they were not the ones to sign it. For example, say client A calls service B, using a token signed by service C. Previously, we were using randomly generated session keys, which meant B had to ask C every time. But with JWTs, B can directly verify that the token is genuine without asking C, because it has C's public key. We still check with C now and then, but that's because the token auto-expires. We use a long-lived master token stored in a cookie to generate new short-lived ones.
- carapace 10y agoReminds me of "macaroons". http://research.google.com/pubs/pub41892.html http://research.google.com/pubs/pub41892.html "Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud"
- arnarbi 10y agoIt's unfortunate that the JWT encoding scheme of the signed data (non-normative JSON -> base64 -> concatenate with a dot) does not lend itself well to hash-chaining. JWTs could have been a great standard encoding for macaroons. (disclaimer: I'm an author of that paper)
- sk5t 10y agoSolid point... I suspect many of the shortcuts in JWT (e.g., not making any attempt to normalize / canonicalize before signing) are a backlash against the implementation headaches of SAML, specifically XML-DSig and the troubles associated with "tell me the ID of the signed element and I'll verify it's signed" mode operation.
- skybrian 10y agoI didn't understand this part: "if your application maintained a list of key/algorithm pairs, and each of the pairs had a name (id), you could add that key id to the header and then during verification of the JWT you would have more confidence in picking the algorithm" This implies there's a security benefit, but I don't understand how it's better than checking the alg parameter against a whitelist. Perhaps if you're using non-standard names for algorithms, that guards against mistakes?
- davb 10y agoXHR? Sessions. REST? Bearer tokens or OAuth. Third party trust? JWT.
- blazespin 10y agojwt are the capability model. They are not forgeable and they expire. You can revoke them by telling the database to ignore them by the token id. If you have a services based model you can pass them along and they can verify your capability without going to the db.
- geuis 10y agoHow does this avoid the problem of a 3rd party getting your jwt token? Then they can do any request as you.
- intrasight 10y agoTying the token to an IP address will largely ameliorate that issue. As always, there is a tradeoff of security and convenience. I've worked at facilities with no internet access, where hard drives were removed and put in safes at the end of the day, and that had "leper lights" which flashed when unsecure people like me were present. Very secure but hardly convenient. You always need to ask yourself what it is that you are securing.
- levelist_com 10y agoYou should not tie any functionality, user experience, and last but certainly not least, security to an IP address. IP addresses can be spoofed rather easily, using public wifi, hotel/guest networks, and even certain ISPs means the rotating of IP addresses on each user request.
- intrasight 10y agoAdding an IP lock to a token can only increase security - it cannot decrease security. And if you wish to be secure, then you wouldn't use public wifi.
- levelist_com 10y agoWhat you're doing is increasing complexity, even if marginal, for no benefit and to the inconvenience of your users; Sometimes, increased complexity does introduce insecurities, but I digress. The developer has little to no control over what type of network (wi-fi, public hotspot, hotel, corporate, private, etc..) a user accesses the site with and the user couldn't care less how sessions are managed (for the most part), all they know is if their token becomes invalid on each request because they are using a network that pools and rotates IP addresses b/w users/requests, forcing them to re-authenticate with each request, well, you're going to have some very unhappy users.
- jcoffland 10y agoThis is a practical implementation of something I described on stackoverflow in 2013. http://stackoverflow.com/questions/319530/restful-authentication/19369619#19369619 http://stackoverflow.com/questions/319530/restful-authentica... The discussion there is rather interesting. The problem of invalidating logins is discussed. I have not found any satisfactory solution to this problem. You can set a timeout on tokens but then the user would have to log back in periodically. If the software can renew the token automatically then there is nothing to stop an attacker with a stolen token from doing the same, indefinitely. Still, in many situations these problems are no worse than compromised session based logins.
- niftich 10y agoSerious question: are there any opinionated frameworks that use JWT for session-like or session-replacing ways? There was one was linked in this thread [1], but how did framework authors tackle this domain? Is everything discussed here entirely homegrown, ad-hoc? Is this something that every one of us has to read up on and re-implement every time? [1] https://github.com/hharnisc/auth-service https://github.com/hharnisc/auth-service
- hit8run 10y agoA similar approach are encrypted cookies. You can take data and sign it. The server can then check if the cookie data is correctly signed and accepts or rejects the data in the cookie. This approach also scales horizontally. I use it for a while now in go (http://www.gorillatoolkit.org/pkg/sessions http://www.gorillatoolkit.org/pkg/sessions). If you want you can also encrypt the expiry date into the secured cookie.
- spriggan3 10y agoA few years later : "JWT in place of sessions considered harmful".
- lukeh 10y agoAh, Kerberos :-)
- stephenr 10y agoI've had this "them: we should use JWT, it's easier to scale; me: the customer has 200 clients, they don't need to scale shit, sessions are fine" argument before, and honestly at this point I'm pretty convinced JWT isn't a replacement for session auth. The one place I can see it might be useful, is when you need to give a third-party system some kind of access to your API, as an alternative to storing a secondary hashed field(s) for api keys.
- erpellan 10y agoThe assertion that cookies require server state is wrong. A JWT would easily fit inside a cookie. Or a URL for that matter.
- ams6110 10y agoFunctionally, sounds a lot like http basic authentication, only more complicated.
- jcadam 10y agoSo, I've started working on a new project recently, and thought I'd use JWT (instead of Ye Olde cookie-based sessions). After working with it for a bit, I've decided that I can probably get away with using it for authentication, but definitely NOT for authorization. I'm using a kind of RBAC and storing Roles in the JWT just seems like a bad idea. Header size is one issue, but also there is the problem of granting/revoking a role and having that change reflected immediately (rather than waiting on the token refresh window). So, now my API requests happen thusly: "Ok, I have a valid token for User X, so I accept that this request came from User X. Now, let's check User X's roles in the database to see if they have permission to perform action Y on resource Z..." Hmm... I'm not sure this feels right.