19 ms·
Stop using JWT for sessions (2016)
- JamesThomason 8y agoHi if you loooking for good solution for extract data. I can recommend https://parserr.com/ https://parserr.com/
- pentestercrab 8y agoThis JSON Web Token Security Cheat Sheet[1] or this python script[2] are both quite useful when reviewing anything using of JWTs. [1] https://assets.pentesterlab.com/jwt_security_cheatsheet/jwt_security_cheatsheet.pdf https://assets.pentesterlab.com/jwt_security_cheatsheet/jwt_... [2] https://github.com/ticarpi/jwt_tool https://github.com/ticarpi/jwt_tool
- todd3834 8y agoThose are great! I find the OWASP cheat sheet[1] useful as well but I’m going to keep the pentesterlab cheetsheet bookmarked for easier to digest to similar data. Thanks for sharing! [1] https://www.owasp.org/index.php/JSON_Web_Token_(JWT)_Cheat_Sheet_for_Java https://www.owasp.org/index.php/JSON_Web_Token_(JWT)_Cheat_S...
- suff 8y agoObviously written by a non-expert. Half of the claims here are false and he only references other blogs. OWASP is nowhere to be found.
- iancarroll 8y agoI’m hoping this is sarcasm.
- 0xffff2 8y agoThis comment is completely unhelpful without detailing which half.
- franciscop 8y agoObviously written by a non-expert /s
- CiPHPerCoder 8y ago> OWASP is nowhere to be found. Is this satire?
- Charlie_26 8y agoThis seems to be targeted at web apps. I take it I don't need to remove JWT token support from all of my mobile applications?
- KirinDave 8y agoThe problems with JWTs go well beyond "how do we do session invalidation." However, since mobile apps tend to be SSL encrypted on devices that don't reveal contents to users, you've often got a lot more leeway than the transparent condition web apps suffer. I know my app didn't have any real security challenges until we had a website with actionable data.
- justaaron 8y agowhat about setting a secure cookie with a jwt, and expiring it when you log-out? what is the utility in server-sessions? (aside from the ability to revoke it at any time from the server.)
- anon1252 8y ago> and expiring it when you log-out? and how would you do that if the user doesn't actively log out of a service?
- justaaron 8y agoset the cookie in the response to their next request to you? specifics depend upon the language and framework used on the server, etc...
- detaro 8y agoDo you mean "delete the cookie" with "expiring it"? Then that doesn't help against an attacker which already has obtained the JWT, they can still use the JWT until it's expiry.
- justaaron 8y agowhat i propose: 1) login = sending username and hashed password (over tls) that does a bcrypt etc, compares to bcrypted etc hash in db, if correct = provide a jwt set as a cookie with "secure httpOnly", jwt should be logged. 2) logout = request to server, server sets cookie with "token=empty;expires:1970yaddayadda" as it's httpOnly there's no client-side messing baout with the cookie otherwise 3)_all pages send cookie with each request, so must be tls upon logout, cookie has empty token, must be re-set with new token. old token, if stolen, can be compared with logged history, etc. what do you see, in terms of flaws?
- justaaron 8y agoso, what about a single-use token you exchange for another token (or not)?
- csours 8y agoWe have a requirement that users be logged out after 30 minutes of inactivity, so JWTs are perfect for our use case.
- drinchev 8y agoWhat about a stolen user password and an actor, who already uses your token? Can the targeted user kick him out by resetting his / her password?
- nbevans 8y agoSure why not? Each user account has a counter or timestamp on it in the user registry. If the JWT token in the request passes crypto validation but it has an older counter/timestamp than held in the user registry then it is deemed invalid and the user must re-authenticate. This is still a horizontally scalable design.
- gravypod 8y agoThen you are back to statefulness if you need to check this magic "count" every request.
- nbevans 8y agoYou can horizontally scale counters with CRDTs, specifically the G-Counter. Whereas it is harder to scale a (usually) opaque blob of application state a.k.a. session state.
- aaaaaaaaaab 8y agoThis “user registry” of yours sounds an awful lot like a traditional session table in a central DB. Could you elaborate a bit on that in terms of horizontal scalability please?
- nbevans 8y agoUser registry can scaled however you want it to be. It is simply the service that manages user accounts, passwords, permissions, and of course issues the JWT tokens. Equally it can be a horizontally scaled micro service.
- H00tyMcOwlFace 8y agoBurp Plugin for JWT decoding / attacks https://github.com/mvetsch/JWT4B https://github.com/mvetsch/JWT4B
- drinchev 8y agoTop reason for me always was : > You cannot invalidate individual JWT tokens And there are more security problems. Unlike sessions - which can be invalidated by the server whenever it feels like it - individual stateless JWT tokens cannot be invalidated. By design, they will be valid until they expire, no matter what happens. This means that you cannot, for example, invalidate the session of an attacker after detecting a compromise. You also cannot invalidate old sessions when a user changes their password. > You are essentially powerless, and cannot 'kill' a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with.
- tehlike 8y agoNot true. Encode a token and validate it against a constant, which you change in case of a compromise.
- anonymousJim12 8y agoHow do you encode it in such a way that you can invalidate individual tokens? How do you distribute that information among your services?
- dperfect 8y agoIn the past, I've compared the "iat" (issued at) value with a column in the users table called "invalidate_tokens_before". If I need to invalidate tokens for a user (for my use case, it would always be all tokens for a user at once), I just touch that timestamp column. True, it still required a db lookup (one that happens anyway), but I found that easier to manage than storing and managing session tokens.
- ivanhoe 8y agoAnd how is that better than using sessions in the first place? What is your gain?
- 8y ago
- fatpigeon 8y agoPrevious discussion: https://news.ycombinator.com/item?id=11895440 https://news.ycombinator.com/item?id=11895440
- anon1252 8y agoThe idea of JWT is basically you give your user a "token" that can be used against many "services" while servers don't have to persist the state of that token, just be able to read the encrypted token, and trust the information in the token. The obvious issue is the server cannot easily revoke that token without blacklisting it, therefore persisting that token somewhere on a blacklist on the server. If you are going to make a lookup for a token in a blacklist you might as well look up for a session ID to being with.
- redbeard0x0a 8y agoTraversing a list of 100,000 users/sessions in a db to pull up the session is a different beast compared to traversing an in memory list of 10-100 revoked JTIs in redis. It is a lot less data to store and optimize (the full session vs. a small list of revoked JTIs)
- anon1252 8y ago> Traversing a list of 100,000 users/sessions in a db to pull up the session is a different beast compared to traversing an in memory list of 10-100 revoked JTIs in redis. It is a lot less data to store and optimize (the full session vs. a small list of revoked JTIs) I don't see why one can't use redis to persist sessions at first place and why your list of revoked token would be limited to 100.
- luhn 8y agoIt's not explicitly limited to 100, but only a small portion of tokens will be revoked, so your revocation list will be small.
- finder83 8y agoIt does depend on how many users you have and your TTL for the JWT, but if you have a 10 minute time to live, you only need to store the revocations for 10 minutes in redis since otherwise the tokens themselves expire. (Just an example, sub 10 minutes with 24 hours or whatever)
- staticassertion 8y agoCan someone explain the Cookie vs LocalStorage thing? You can access cookies from Javascript, so how is localstorage worse? Assuming an attacker can execute arbitrary js in the browser (the model provided by the article). edit: Thanks for the answers - httponly, makes sense.
- nbevans 8y agoYou can't access a cookie from JavaScript if it is marked with the HttpOnly flag.
- miskin 8y agoIf you set cookie httpOnly, Javascript cannot see it. So some malicious third party library or XSS attacker cannot steal session. It can still do requests and cookies would be included, so stealing is the main difference.
- ATsch 8y ago> You can access cookies from Javascript, so how is localstorage worse? You can access it via JS only if you don't set the httpOnly flag on the cookie.
- labourcurious 8y agoThe author glosses over this but what they mean is that you can set the HttpOnly flag on cookies to prevent them from being accessed via JavaScript.
- deathanatos 8y ago
- jesseb 8y agoFrom my time browsing HN, the consensus seems to be "don't use JWTs". What is the preferred method of client authentication for simple APIs these days?
- scient 8y agoOAuth access tokens? The difference being that JWTs contain information directly, as well as an access token to hit any APIs, while an access token contains no information on its own - thus solving the revocation issue. Now I don't think anyone really uses JWTs for API authentication, or they should not at least. APIs should still be gated by access tokens.
- deleted 8y ago[deleted]
- esotericn 8y agoDisclaimer: not a front-end dev. I'm not sure what the issue is with a simple session token, to be honest. OWASP have guidelines on this that cover the bases pretty well, I think. Store hashes, not tokens directly. Expire them server side. Don't accept user input (within reason). You generate and offer the tokens, you know what they look like, you can bounds check / sanity check appropriately. Perform some additional checks as necessary (e.g. invalidate a session if remote IP changes). If you have more security critical parts of the infrastructure, require re-authentication and more short-lived sessions for those. The obvious example would be how Amazon pretend you're "logged in" until you go to click My Orders, then you get auth gated. I tend to think that people over-complicate this stuff a lot as a premature optimization for scaling. A simple python script backed with some DB will do hundreds of hits a second to an auth service without really trying. If you need more than that, optimize. If you need more than 10k hits a second on a regular basis then you're probably at the point of hiring someone who knows this stuff. Just my 2c.
- detaro 8y agoTokens checked against server-side sessions. OAuth 2 is common to obtain them. (The tokens can of course be JWTs if you want their content to be transparent, but the key is to not rely on the metadata in the token alone for verification)
- ThePhysicist 8y agoI used to be very opposed to JWTs but I can see some interesting use cases for them now, at least when using the variant based on public key cryptography. For example, if you need/want the ability to verify token validity locally (i.e. without making a call to you auth backend) they are very handy: Generate a token, sign it using the auth backends' private key and clients can verify it using the public key. That said, I wouldn't use them as a default authentication mechanism as invalidation requires a connection between clients and auth backend again, as many people here pointed already out. It might still be easier to establish such a channel though than continuously verifying traditional tokens via the backend, which you can solve differently though as well: For example, for our APIs at KIProtect we cache validity information for (hashed) access tokens for 60 seconds on the API server, and we refresh the tokens in the background 30 seconds before they expire (if triggered by a request). Like that we can ensure that invalid tokens cannot be used after a short grace period (60 seconds is good enough for us) while not slowing down clients that perform many API requests as the token needs to be fetched only for the first request and will then never leave the cache (as it gets updated) if the client performs at least one request roughly every 60 seconds (or more often).
- indeyets 8y agoIt's an interesting reading (together with second part), but should be taken with a grain of salt. Stateless sessions are useful under load and not necessarily under reddit-size load. I like 2-layered setup actually with long-expiration (1 year) "session" cookie kept on `auth.example.com` domain and short-lived (1 hour) JWT-cookie kept on `example.com` domain. JWT can optionally include permission for dangerous operations which is not automatically granted. You still need redis to take care of forceful expiration, but that would be very simple call to the small list (1 hour of force-expirations if you reissue jwt-tokens on hourly basis), not data-fetching calls. We can keep this in a tiny redis-cluster colocated with frontend machines. JWT would have enough data to personalize cached templates. This will render really fast. API-backend, database and larger redis-storages can be kept deeper in logical server-room and be accessed only on cold requests
- nine_k 8y agoI generally agree, but to me "short-lived" would be below a minute. The point of the short-lived token is to make many clustered requests (as when a page loads a lot of assets) cheap because you only need to check a token. Any other human interaction, which takes longer, should go through the server-persisted session logic.
- indeyets 8y agohi ;) I guess that depends on exact use-cases. Below-a-minute is fine for tightly controlled environments, but publicly-used web-apps usually have a sweet spot with TTLs between 10 and 60 minutes. More requests = shorter TTL, less requests = longer ttl (as it would be counter-productive to have more auth-requests than data-requests)
- nine_k 8y agoIndeed hi! :)
- nbevans 8y agoJWT is an authentication token - it isn't session state. Session state changes during the lifetime of a session. Whereas the authentication token does not - other than for renewals. Overloading the authentication token to also store unrelated domain concepts such as shopping basket items is a gross abuse of its purpose. Given that generating a JWT token is computationally expensive I really doubt that many people are doing this like the premise of the article suggests.
- the_af 8y agoI think by payload they mean the JWT can "store" actual permissions. Not state such as a shopping cart, but a payload composed of permissions granted to this client to do this or that in this app.
- nbevans 8y agoStoring security claims i.e. permissions in the JWT token is a valid use. This isn't session state. Those permissions don't change, they are in fact cryptographically immutable, until the next renewal of the token. Whereas by definition "state" does change.
- the_af 8y agoI know it's a valid use (I use JWTs!). But it is state, which is why you have a payload and not merely an id. State doesn't have to change; that's mutable state. (Permissions do change, by the way, only less frequently than a shopping cart!).
- ivanb 8y agoMany in the comments are curious about blacklisting JWTs. No, you don't need to put the whole token on a blacklist. Give your tokens reasonably unique JTI claim[1] and put the affected JTIs on the blacklist. The benefit of JWTs is that token blacklists are usually much shorter than hypothetical token whitelists. [1] https://tools.ietf.org/html/rfc7519#section-4.1.7 https://tools.ietf.org/html/rfc7519#section-4.1.7
- the_af 8y agoWhat if the blacklist becomes unavailable? The author addresses this in part 2.
- xyzzy123 8y agoThen your application is unavailable, just like it would be if your session table went away? I don’t get this complaint. The advantage is that you can use a loosely consistent datastore with expiring entries and few records at any given time. There’s lots to love about the approach.
- the_af 8y ago> Then your application is unavailable, just like it would be if your session table went away? The author replies: "congratulations, you've just reinvented sessions, with all their problems (like centralized state) and gained nothing in the process", and also with an implementation that is "less battle-tested". My own opinion: loose consistency can work in some circumstances, but seems a security risk in others.
- Spivak 8y agoBut we've drastically reduced the amount of central state, the complexity of managing it, the time it takes to access it, the danger of losing it, the performance impact of updates to it, while making the happy path to your site faster. Revolutionary, maybe not, a solid improvement on the traditional design of sessions, I think so.
- franciscop 8y agoIf an attacker can read the user's localStorage you have much bigger issues to worry about: XSS, physical access, no TLS, etc. With any of those, the token is the least of your concerns; an attacker can make API calls, read the data, etc anyway, no matter if its JWT or sessions. So, IF (which is a big if) you implement everything correctly then you have to do two "extra" steps with each tech: - Blacklists (or Whitelists). You _do_ need these, because you want users to be able to logout. Then it's a lot more like sessions... oops. - CSRF protection for sessions. These become trickier to manage in SPA and just become sort of a "token" that you need to refresh on each call... oops. It seems that the shortcomings of each technology makes it to lean towards the other. The good news is that both of them are theoretically secure, the bad news is that to reach that level you have to do a lot of work (on both!) with a lot of room for error. That is why I personally prefer JWT with SPA and CSRF with traditional servers, since the amount of new code that I have to write is a lot lower so chances for error are quite lower. For instance, see the (very brief) documentation of the CSRF for my project server.js: https://serverjs.io/documentation/router/#csrf-token https://serverjs.io/documentation/router/#csrf-token . If I had more time I'd write something similar for JWT.
- donatj 8y ago"If an attacker can read the user's localStorage" 9/10 the attacker is the user.
- franciscop 8y agoSince the topic is authentication, that is an independent concern, right? Edit: unless you mean something about making the user do something. If it's running a script, it's the same in both ways. Now, if it is about the user retrieving and sending the token, the attacker could still ask the user to manually get the session cookie or the localStorage JWT. The cookies might be protected not to be accessible from JS, but they are still in the browser.
- peter_retief 8y agoI used JWT for a SPA site using Vuejs with Django backend. The project became a nightmare and I had to abandon it because of the increasingly complex security issues. The client was not happy
- arendtio 8y ago> Unless you work on a Reddit-scale application, there's no reason to be using JWT tokens as a session mechanism. And what should I use when I do work on a Reddit-scale application?
- captn3m0 8y agohttps://paseto.io/ https://paseto.io/ >>Paseto is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.
- KirinDave 8y agoMacaroons. JWTs are a total nightmare from a security perspective in an organization trying to provide a microservice environment. There are way too many potential mistakes permissible in JWTs spec. They nearly always come up when you're stretching across a pair of language environments and a few library versions.
- rhacker 8y agoI mean look at the web page: https://jwt.io/ https://jwt.io/ The fon't is so large, how could it be bad advice? And look at how short that domain name is! AND IT ENDS IN IO WOW, the owner must be really important! And that logo, I mean come on - that was probably designed by 400 italian shoemakers 300 years ago waiting for the right technology to come around to stamp it on. Sorry I just can't take your well reasoned arguments on a web page that has this large red banner and multiple bullet points. This was probably put up by just some guy right?
- captn3m0 8y agoRelevant: https://paseto.io https://paseto.io Platform-Agnostic Security Tokens >Paseto is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.
- manigandham 8y agoIncorrect, these are not comparable things. JWTs are a standardized way to securely encode data into a self-contained token. Cookies are special headers added to HTTP requests to store state. You can absolutely use JWTs as the payload of your cookie. How you pass the session data back and forth is separate from how you encode the session data. Most web frameworks have their own token formats, but you can easily change them to be JWTs. Using the Authorization header just means you're using a different header, and since it's not automatically sent then you don't have the CSRF issues with browsers, but now you have to manage it more manually in your client-side code. Regardless of how you encode your tokens, if you want to do instant expiration or other live data lookup then of course you'll need to manage that on your server, whether it's a database, in-memory cache, or something else. The split between where state is managed is irrelevant to the physical transfer and encoding.
- anon1252 8y ago> Cookies are special headers added to HTTP requests to store state. The topic is more about session VS JWT, not cookies vs whatever local storage is used in place of cookies.
- manigandham 8y ago"Session" does not mean anything. It is state, usually stored and sent in cookies, but just as easily stored and sent as JWTs/Auth.
- anon1252 8y agoYes it does mean something. a session is something that is identified by an ID on the client and is persisted on the server with the corresponding ID. It's a concept. It doesn't have to be stored in a cookie. A session can be represented by a token and stored in any client side storage.
- manigandham 8y agoOk, yes, session is a concept. Session state can be stored in its entirety or split between an ID and body. You can send it all to the client or you can send just an ID and lookup the body on the server. You can send it to the client via the cookie header or via the Authorization header or something else. You can encode the data (sent via cookies or auth header) as a JWT or your own encryption scheme. These are all different technologies working at different layers, which is why comparing JWTs vs cookies vs sessions doesn't really make sense.
- coltonv 8y agoWe use JWT for validating simple handoffs from server to server, allowing someone to briefly access a resources such as downloading a file from a server designed to do that. We set the expiration to only an hour, and JWT is excellent for this use case as it means we don't need to implement our entire login and database workflow on a machine that just serves files.
- ninjakeyboard 8y agoI wrote a scala JWT library on a weekend when I was more of an intermediate developer (6 years ago?) and it started to be used. But I never ran it in production and flaws were found in it. As a consultant 5 years later I found a customer using it and told them to use someone else's :). I'm not a security expert - one of the strengths is one of the weaknesses - that's it's a simple spec to implement so your average Joe can implement it, but imperfectly.
- jcadam 8y agoI use JWT for authentication on my current project. And I eventually ended up having to check the user's 'role' in the database for authorization before I let them do anything anyway (and consequently, revoking someone's user role or suspending their account has immediate effect). I saw many examples on the net of people putting role/authorization and various other types of session information within the JWT and it just looked insane to me. Ultimately, I think what I ended up with is only a minor win over just generating random tokens and maintaining a "sessions" table. Probably not worth the effort and likely won't use JWT again.
- wheresvic1 8y ago> I saw many examples on the net of people putting role/authorization and various other types of session information within the JWT and it just looked insane to me. Why is this crazy? If you encrypt your JWT with a private key that is only known to the server, then any modification to the JWT will lead to an invalid token. The only thing here is that the list of roles granted is visible to the user if they were to decode the JWT, which is something you might not be entirely comfortable with but I don't think it's totally crazy.
- jcadam 8y agoI suppose it depends on the application. I wanted to be able to revoke a user's permissions and not have to wait until token expiration for them to be locked out.
- mgraczyk 8y agoLike many other articles on JWTs, this one mischaracterizes the trade-offs that exist. You can invalidate individual JWTs, you simply store the blacklisted token IDs in a table in your database. Implemented naively, this results in a request flow in which the database is still accessed on every request, defeating one primary purpose for using JWTs. However, there are better ways. Since the blacklist is just a collection of random token IDs, it isn't sensitive. You can store it anywhere, including in memory in your web servers or in a distributed cache. You can wait during blacklist/token invalidation events until the newly blacklisted token has been propagated. Using the above, JWTs enable a design space trade-offs that doesn't exist with session tokens. You trade slower blacklist requests (logout, one time confirmations, etc) and minor auth complexity for one fewer db access per request, more flexibility, and more uniformity if you use oath or similar. All of this is around 90 lines of python in my Django site.
- KirinDave 8y ago> Since the blacklist is just a collection of random token IDs, it isn't sensitive. You can store it anywhere, including in memory in your web servers or in a distributed cache. You can wait during blacklist/token invalidation events until the newly blacklisted token has been propagated. This is very dangerous advice. If you're advocating for the addition of a fast blacklist storage, you really haven't changed your previous pattern complaint, but the dangeous bit of your advice is implying that it's simple to store "anywhere" such as "in memory in your web servers." That is a bad idea. If your authentication model is depending on an explicit stop-list to invalidate tokens, then you need to take the integrity of that data set very seriously or be at serious risk of credential replay attacks. A loss of integrity in this data store in unacceptable. Even some eventual consistency can be dangerous (but is generally accepted as a risk if the time envelope is acceptable). It's much better (from a security standpoint) to have very short lived tokens and constantly revalidate. The revalidation cycles CAN be full database cycles since they occur at a reduced rate, and you can then have more sophisticated policies there without too much trouble. > All of this is around 90 lines of python in my Django site. I don't doubt it, but trying to scale your advice to a product or to an environment with actual concurrency opens up a lot of complications you're not considering. JWTs are, by and large, just an inferior spec with too many brittle edges. You need to be really careful to properly implement JWTs in your environment. You're much better off either sticking to rich session tokens or using something like Macaroons. P.S., not only is the phrase "black" list steeped in a history you may not realize you're invoking, but it's much less precise than the term "stop list". Please do consider this.
- mmgutz 8y agoThe arguments here says you can't invalidate a JWT. Exactly!! JWT IS A TOKEN. You can use it for refresh (invalidation & renew) and access (authorization) tokens. There's so much disinformation about JWT. The end result is some not invented here "JWT".
- haggy 8y agoYes but you're missing an entire chunk of context. The problem mentioned in this article is saying it's bad that you can't invalidate a JWT WHEN using them for authentication and/or authorization. This makes it impossible to do things like disable/kill a session that has been deemed hostile or dangerous (like a stolen account). Now to build on this, good defense-in-depth can help here. For example if you use JWT only for authn but kept authz 100% server-side. You could then revoke the users access to everything so that the blast radius is confined. The bad actor could still authenticate into the system but would not have access to much or any resources.
- AndrewSChapman 8y agoI'm not 100% sold. I think JWT's are fine in some situations as long as you know the limitations. Regarding session invalidation, I would handle this in two ways. 1. Support a "Log everyone out" function by storing a simple version number in the JWT. If the version constant in your app is different to the number in the JWT, it is invalid. 2. Support a "I need to logout user X function" by storing a blacklist of tokens in your RDBMS. If your RDBMS goes down, you have much bigger problems. A blacklist will be very short, and often completely empty, so lookups will be significantly faster than checking a session table. You could also use Redis or an application cache for storing the blacklist, with an RDBMS fallback. Regarding storage, there's nothing stopping you putting your JWT into a cookie with the HTTPonly flag set. So long as you're not storing too much in token, they will be less than 4k and so will fit.
- cweagans 8y ago> 1. Support a "Log everyone out" function by storing a simple version number in the JWT. If the version constant in your app is different to the number in the JWT, it is invalid. If you've got the iat property, you could just use that. i.e. anything issued before x time is invalid.
- enraged_camel 8y ago>>2. Support a "I need to logout user X function" by storing a blacklist of tokens in your RDBMS. Again though, the whole point of JWT is to completely avoid server-side state management. The moment you store state somewhere (whether a list of valid tokens or a shorter list of invalid tokens) you have re-invented the concept of sessions, so why not use that instead?
- AndrewSChapman 8y agoHow about instead of "the whole point of JWT is to completely avoid server-side state management" we think of it as "the whole point of JWT is to reduce the overheads of server-side state management". In my answer above, I was pretty clear about how the load on the database can be significantly reduced with a blacklist and optionally Redis out front, thus allowing JWT to significantly reduce the burden on the database.
- ccleve 8y agoSorry, I'm going to be a contrarian here. JWTs can be good. First, cookies-vs-local storage is a non-issue here. If a JWT is small, it can be put in either location. The only real issue is, should session state be on the client or on the server? Suppose you have an app with large numbers of users, doing hundreds+ of queries per second across many boxes. If you put session state on the server, then you must either 1) have sticky sessions, which generate problems when a server goes down; 2) have a central session server, which generates scalability and reliability problems; 3) have a Redis-like distributed system, which either a) must do one or more server-to-server round trips on every client call to validate the session, or b) cache session information on a node. When latency matters, an extra server-to-server round trip is a non-starter. And if you do server-side caching, then cache invalidation and JWT invalidation present similar problems. ("There are only two hard things in Computer Science: cache invalidation and naming things."). Server-side sessions don't really buy you much. If you're using a system that has them built in, lovely, but if you're not, it's a lot of extra work. JWT is a good solution to the problem. You can store small amounts of session state on the client and simplify the whole system. You can avoid having to do lookups to determine state variables. (What database was the user connected to? Is he in mode A or mode B? What timezone? What language?) Put a short expiration on the token (a minute? five minutes?) and force the user to re-validate against some data store after that. The benefit is that you greatly reduce internal server traffic at the cost of not being able to invalidate a session within your short timeout interval. Depending on your app, letting someone remain an admin for an extra minute is not a big deal. And if it is a big deal, you can still handle it by sending a message to each node telling it to invalidate that particular user. A pain, yes, but the tradeoffs may be worth it.
- CiPHPerCoder 8y ago> If you're using a system that has them built in, lovely, but if you're not, it's a lot of extra work. They're built in with PHP and most Node.js frameworks I've ever worked with. I'm not sure about Python, RoR, etc. web frameworks but the engineering overhead for adopting server-side sessions should approximate 0, since they're usually the default.
- 8y ago
- tebruno99 8y ago"You cannot invalidate individual JWT tokens" This is not exactly true. There are lots of things you can do to expire tokens. For instance, every JWT has a creation date stamp so you could say on the server side all tokens created before Time.Now() no longer accept as valid. Allowing users to expire ALL tokens, etc.
- nneonneo 8y agoSo you need to maintain state whenever tokens get invalidated, and check this state on every token-bearing request. At that point why not just fetch the rest of your session data out of your database? And if it’s some kind of global cutoff - well, now every revoked session comes with a log off for every user, which is a usability nightmare.
- zimpenfish 8y ago> you could say on the server side all tokens created before Time.Now() no longer accept as valid But that's not anywhere near "invalidate individual JWT tokens" - you're invalidating -every- token before `Time.Now()`. Unless you store a different "valid after" time per user and then you're back to storing sessions in the DB, aren't you?
- joepie91_ 8y agoAn update that has not been added to the article yet due to a lack of time: even if you do have a valid usecase for stateless tokens, you probably want PASETO[1] instead of JWT, due to the inherent cryptographic design flaws within JWT[2]. I'm probably not going to engage in the discussions on here this time, as it was an incredibly mentally draining experience last time; the vast majority of arguments were either already addressed in the article itself (which the commenters clearly had not read and understood in full), or argued against a misrepresented claim. It got so bad that I had to dedicate a whole second article to it[3]. If you have a genuine question or concern about the article rather than an Angry Internet Comment, feel free to e-mail me; my contact details are at the bottom of the article. No guarantees on response time as I'm juggling a lot of other plates at the moment, but I'll eventually get around to responding :) EDIT: Another addition... this presentation[4] gives some insight into the history of JWT-for-sessions and why it became so popular. A spoiler: it wasn't for rationally-technical reasons. [1] https://paseto.io/ https://paseto.io/ [2] https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba... [3] http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/ http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-fo... [4] https://youtu.be/GrLtOjCTB1s?t=1h2m44s https://youtu.be/GrLtOjCTB1s?t=1h2m44s
- Double_a_92 8y agoCan anybody recommend a tutorial or book on how to do Authentication properly? Say for the usecase SPA + REST API. If I google quickly I mostly just find tutorials that turn out to be ads for some 3rd party service. Or other beginner tutorials that don't seem very trustworthy. I feel like I'm missing something, since this should be a very common use case for most (web) apps. (Bonus if it also covers User Authorization, i.e. different roles that are allowed to do things or not.) Thanks.
- Exuma 8y agoCan someone explain how this is similar/different from the default ways Ruby on Rails stores sessions? I know they're encrypted and signed, and all the session data is stored in the cookie. This seems to work great, what is the downside of just doing this method (for say, bigger sites)?
- bradstewart 8y agoThe only downside I've ever encountered to Rails default sessions involves authenticating against other backend endpoints from JS applications served by Rails. Which really has very little to do with Rails itself...
- Exuma 8y agoSo do you know the difference between that way and the JWT way? All these different methods are kind of confusing, and it seems Rails does it a great way, and everyone hates JWT... but arent they basically the same thing?
- jopsen 8y agoWow, I wish people would stop complaining about JWTs.. JWTs are a silver bullet, but it's nicer than rolling your own signing scheme. Don't run with scissors, don't do security if you don't understand your primitives..
- CiPHPerCoder 8y agoThe alternative to JWTs isn't rolling your own signing scheme. Use PASETO instead. https://paseto.io https://paseto.io But the issue being discussed in this article is about how JWTs are being used, not JWTs themselves. > don't do security if you don't understand your primitives.. The security industry needs to do more to provide tools that do security for people who don't understand their primitives.
- anon1252 8y ago> JWTs are a silver bullet, but it's nicer than rolling your own signing scheme. you can use HMAC to sign session cookies as well, the issue isn't about signing.
- Tade0 8y agoA huge part of the issue with JWT is that it's often used wrongly. I'm currently in a project where JWT is used. We have a list of searchable items and each one of them holds a gallery of photos - up to 5MB per photo. The issue at hand is that these photos are served from a certain endpoint which we eventually want to secure, but the back-end's idea here is for the front-end to download the photos via XHR putting the token in the Authorization header - they refuse to send the JWT via cookie saying that it's "incompatible with JWT".
- sebringj 8y agoShort lived JWT is ok for stitching desperate micro services together as it saves round trips to verify things but I prefer mystery tokens when using more intimate services that have access to similar underlying stores to verify them. Basically use them appropriately and they are fine.
- haloux 8y agoNone of what the author is writing about concerning the inability to revoke stateless tokens is particularly novel. We have the same problem with SSL/TLS PKI. Once a cert is revoked, there is no reliable way to ensure that its revocation is enforced among all clients. The world has proved to be content with accepting this risk. Protip: be sure to read what I said before you use the b-word in your responses. Additionally, the sarcastic flowchart that is included in part 2 of his post makes some pretty open-ended assumptions. "Just take down the blacklist server" is my favorite. edit: clarification.
- arithma 8y agoAre there any engineering books that have a collection of best practices for internet engineering problems similar to this one? I find that most of this information is learned colloquially, or through what other frameworks do.
- novaleaf 8y agoHow I use JWT: an encrypted storage of the user's authentication credentials, stuffed into a persistent domain cookie. Thus, JWT is just a standardized way of encrypting a json payload and storing/retrieving it in a cookie. works for me (my arch is stateless), and seems orthogonal to the arguments described in the article.