-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dangerous and incorrect information in README #63
Comments
Some very well thought out and articulately expressed concerns that are certainly giving me some food for thought as someone who's just started looking at the repo. I was looking for a quick example to create a JWT auth working example with Node. My interest in JWT is to provide a modern best-practice approach to session management for both REST API and js client while avoiding CORS issues. I am mildly interested in security but this isn't my motivation for using JWT although I appreciate the role that tokens can play in more comprehensive secure approaches such as OAUTH. As I first read through this repo it did strike me as including a lot of notes that the author has collected as they are building their knowledge of JWT usage etc. Although I have little investment in this repo I am inclined to believe that there is a place for a platform specific, minimalistic working example of login/logout with some supporting tools,references. As a foundation for on-boarding skills and as a starter I think the aims of this repo are good but perhaps the README does need a serious rewrite and a refocus on the aims of this type of usage of JWTs. I'd be happy to try to suggest something .. joepie91 - you clearly have a good undertanding of the issues .. could you provide some thoughts on what the real benefits of this kind of usage of JWT's really is? |
Hi @joepie91, we are stoked that you have found and read our notes on JWT! We respectfully disagree that the content of these notes is "Dangerous".
Granted, many websites/apps (which are not using 3rd party tracking cookies) fall under the
Yes, the primary purpose of JWTs is to is to Our sessions ids or tokens could simply be a random string which gets checked server-side, but we decided to use JWTs to format and sign the session data. Conclusion: let's update the readme to clarify things. 👍 |
Rather than splitting the raised issues into a set of issues as suggested by @nelsonic I tend to agree that the intent and objectives of the implementation should be clarified in the scope of the README. I don't read the issues of @joepie91 as being a criticism of the use of JWTs in the context of web applications as such, or the support of cookies as superior; rather I take the criticism as being that the description of JWT's is presented in a way that overplays or misrepresents the reason for choosing JWT. For me it's enough to be able to operate Firebase and my own services using a common claim that expires. I may extend it to include some state in some cases and not in others and still prefer the approach to using cookies or older access control http authentication approaches. I don't know if I'd necessarily say that the README is dangerous - seems a little strong |
Apologies, it seems I worded it rather vaguely. While the text does contain the word "cookie" in several places, it does not identify it as a specific concept to be legislated; rather, it is provided as an example (and thus the rest of my point remains applicable, and "not using cookies" will not magically remove the need for consent).
This is irrelevant, and a problem of those services. That does not justify using JWT for sessions in your own application.
Aside from the fact that Firebase is extremely poorly engineered, this is an appeal to authority and has no place in a technical discussion. I'm not interested in discussing the decisions of a particular company for a particular product; I am only interested in discussing the merits and downsides of a given approach.
At which point there is no actual benefit to using JWT anymore. Why aren't you just using Not to mention that session expiry should be handled server-side, and so the
JWTs are not related to "web application environments" in the slightest.
Again, just use a battle-tested session implementation for your stack. JWT is the wrong recommendation to make here.
You can disagree, but that's what it is. There are so many ways to use JWT wrong - several of which are alluded to by the README in this repository - that people are bound to shoot themselves in the foot. Yes, it's harmful.
There are no benefits in using JWT for standard web applications, unless you are running at Reddit scale. Some common examples of cases where JWTs are useful:
For standard web application sessions, you should just use a well-tested session implementation for whatever stack you're using (eg. |
It's great to have this discussion as it really challenges some of my experience. Perhaps some context for my personal interest in using JWT ( aside from the fact that I make use of Firebase which I would be interested in learning the poor engineering issues which I will look into ). When creating mobile apps/SPA and particularly when using services sourced from multiple servers/domains I find that I often require a single sign on capability that JWT seems to lend itself to nicely. My understanding is that the use of session cookies evolved over a period in which the security was tightened in the browser and JS space and the introduction of CORS evolved to handle exceptions to this leaving us with a rather hacky solution that JWT goes some way to address. |
Some of the problems are that its JS client library is closed-source and obfuscated with rather unhelpful error output, there's no such thing as "arrays", there are many weird bugs in the client library where you might just not get back a response for unclear reasons, the ACL system uses a non-standard JSON variant that even their own editor doesn't support, the JS API requires to use a pseudo-event API rather than a normal callback API (but doesn't behave consistently), and so on.
Not quite accurate. Your application and third-party APIs are different things, with different authentication requirements. Whereas a token-based authentication system can make sense in an application when talking to a third-party API, this doesn't make sense for your own application, even if it's an SPA. That's also unrelated to "single sign-on", which refers to multiple end-user services using the same login service. CORS is a separate issue, and not really related to this.
In development, you might have certain testing requirements, but these shouldn't affect the approach you take in production. Aside from the fact that most things that are an SPA really shouldn't be an SPA to begin with (SPAs are for webapps, not websites!), there's no reason why you can't use sessions with them. Aside from that, cURL supports cookies fine, and there are many other, better API testing clients like httpie or even http-prompt.
The session is one of the most important aspects of your application. If it's not sufficiently secure, your application is essentially broken and completely vulnerable. That's why eg. storing JWTs in LocalStorage is a terrible idea.
No flexibility is introduced here that 99.99% of developers will ever need, and I've already highlighted some of the problems it introduces, like stale data and inability to invalidate tokens.
This is not unique to JWT; you can do this with server-side sessions just fine. In fact, JWTs cannot be invalidated without introducing (complex) stateful architecture, so sessions actually win out here.
The scaling advantage is that you don't need a single canonical server holding all the sessions (since the data can be stored directly in the token), meaning you can remove a bottleneck. But as I said, almost no developer will ever run into this problem in practice. It's only useful for extremely large-scale projects.
I have yet to see a framework that doesn't support session cookies.
That is their problem. Express was simply one example, well-tested session implementations exist for basically every commonly used framework. The bottom line is that for any developer that is reading this repository, there are going to be precisely zero real-world advantages to JWT, and several drawbacks or even security issues. It's just not a sound technical choice or recommendation, and that is really the end of it. |
@joepie91 I cannot tell you how delighted I am that you have found our repo/notes and invested your time to read it through and give us feedback! Seriously, if I ever meet you in person, I will give you a pallet of what ever it is you like to drink! 🍺 If I make you a contributor on this repo will you review my Pull Request for improving it? 📝 Also, @AshleyPinner, @alfiepates, @sunny-g how did you gentlemen stumble upon this particular discussion? was the issue shared on Redit/Hackernews? (I'm just curious how people find our posts...) |
I have been chewing on this for a couple of days and just can't get on board with many of the arguments against using JWT as a default choice ahead of traditional session cookies in modern SPA and mobile apps. Extending further to use cookies as the transport mechanism eliminates another of the benefits and brings us back to using cookies but ignoring the usual library functionality and rewriting features from scratch which introduces further ambiguity because we end up with duplicate timeouts etc. When I mentioned CORS earlier perhaps it was better to be explicit in pointing out the difficulties of using multiple domains with cookies. Sure, you can set wildcard domains, but if they are sufficiently different then traditional session cookies quickly become unwieldy. It can be argued that most developers don't need their authenticated client to access protected resources on multiple domains but this is becoming far more a common practice rather than an exotic edge case. To understate the advantages of stateless tokens as something that is irrelevant unless you are running a top tier trafficked site is incorrect. Even when we kludge things up by introducing a new layer of state, the decoupling of the session from the server has numerous advantages. |
@nelsonic Looking at 4744cd1, that seems like much clearer wording. The header doesn't seem to reflect the changes, though.
This is completely orthogonal to your choice of session mechanism. Not to mention that most things that are an SPA today, shouldn't be. Using an SPA for a website (as opposed to a web-app) breaks the web.
Such as?
No, it isn't. JWT as a technology is not terrible (even if there are some questionable decisions in the specification) - sessions are just not its intended purpose, and it's a poor fit for that usecase. I'm not saying that the tool is bad, I'm saying that you're using it wrong.
What is your rationale for that?
Addressing it point by point:
So no, that article doesn't bring in any new benefits of JWT that I haven't already covered. It just misrepresents the sometimes-a-benefit (statelessness) as something that applies to every application (it doesn't), and then makes nonsensical comparisons and overemphasizes session performance for the remainder.
As I've said, this is almost never a benefit in practice. You can keep repeating this same point of statelessness over and over again, but it will not make it any more valid or applicable. It is absolutely not a general-purpose requirement.
In which case you have precisely no benefits over a regular session ID of some sort.
This is, also, completely orthogonal to the point. This is purely about where you store your identifiers, not about whether they contain the session data by themselves. And again, security risk.
And that concerns me greatly, because that prominent use is based on ignorance and hype, and comes with many security problems. This is a major step back.
I never said anything of the sort. I've provided several very clear reasons as to why JWT is objectively inferior for session management.
In which case, security problem. Cookies are not optional.
Irrelevant to sessions.
Not possible, because the server needs to retain the ability to explicitly invalidate a session - eg. when the user changes their password or forcibly closes other sessions.
Cookies. Done.
Yet you mention none of them that I haven't already addressed, and taken into account in my conclusions. I'm sorry, but you're defending novel approaches for the sake of being novel approaches, and completely ignoring the objective, technical properties of the different approaches. That's what is called "hype", and it's extremely harmful. |
Offline applications don't need authentication, at all. There's, by definition, no interaction with other systems.
Correct. But in this case, you don't use JWT as your session mechanism, you use it as a single-use token that can be exchanged for a session. There's a very big difference between the two, and the tradeoffs it presents. (EDIT: Of course this assumes stateful microservices, and with 'stateful' I am not referring to the session, but to the service itself. For microservices that carry out stateless tasks, single-use tokens without using a session at all is sufficient, with the single-use tokens being issued by the application server. For application servers talking to microservices, JWT is fine as well - there's no concept of a "session" here, and token revocation can be done by changing the signing key.)
Again, I am not doing any such thing. These are entirely your words.
Then I expect you to elaborate on why it is incorrect, not just say "that's incorrect!" and expect me to take it at face value. I'm concretely addressing every point you provide for precisely this reason.
Why?
That's an empty statement. Misused how? And how does this not apply to values stored in Local Storage? And what does this even have to do with JWT at all given that "cookies" is a storage method, not a session mechanism? Comparing "JWT vs. cookies" is comparing apples and oranges, they aren't even the same class of thing!
I'm not. I have very clearly indicated exceptions where JWT is the right solution. I have also very clearly indicated that JWT is unsuitable as a general purpose session mechanism. Stop putting words in my mouth.
Because there's no reason you cannot use both JWT and sessions, for different purposes. Trying to shoehorn it all into a single mechanism for the sake of it, is completely misguided. Use the tool that is appropriate - "not require new cookies to be created" is a completely arbitrary metric and realistically, not the benefit you are implying it to be.
Again. Not. What. I. Said. Stop putting words into my mouth.
It's a feature that requires stateful sessions of some sort, architecturally. I'm not arguing that this is provided by session cookies - I'm arguing that it is impossible with stateless tokens.
Again, not what I said.
The point isn't overhead. The point is using tried and tested solutions that are known to work well. Reimplementing your own security is a terrible idea in any situation, and that includes this one.
What are you even talking about? Cookie "refreshes" are handled inline in HTTP responses by sending along a new cookie - there's nothing extra involved here aside from updating the session store, which I've already covered in my Redis example. If you think there are other performance considerations, then list them.
Again, not what I said.
Yes, they are. The only reason you would ever want to use JWT for sessions is because the alternatives are worse or impossible, and that is an extremely rare edge case.
I'm only treating security as an absolute when it is an absolute. I've also addressed possible ways to solve it, and explained how they are not a good solution as compared to sessions because the net result is still worse. If you think there is a case or solution I'm missing, then mention it. Stop vaguely alluding to "other options" without ever actually explaining what they are. Right now, as far as I can tell, you are bluffing.
Repeating your assertion doesn't make it any more true. I've already covered why this is false, and compromising on security for hype reasons is not acceptable.
There is no "greater flexibility". Again, if you think there is, explain how.
No. I just expect somebody to provide solid, well-argued, technically correct arguments, if they wish to change my views. You have not done so.
... and that would be a perfect example of such a fallacy. The bottom line is that half your statements are putting words in my mouth that I have never uttered, nor implied, nor intended. The other half argues for unnecessary compromise in security, or makes hand-wavy claims about there being "other benefits" or "other solutions" without ever going into it any further. Frankly, I'm tired of this - I don't think this discussion is going to go in a constructive direction, and it's muddying up the thread. The only reason I keep responding, is because of the risk of people being misinformed by your non-arguments. If you want to keep believing that JWT is the holy grail despite having no technical arguments to support that notion, then that's your choice - but you will not convince me unless you come up with actual technical arguments, and continuing to repeat the same assertions over and over again is not going to help anybody. To summarize my points for those skimming over the entire discussion:
(Reddit uses stateful sessions, by the way.) |
I believe that the intent of this repo is to pave the way for implementation of a mobile hybrid SPA and the use of JWT as a replacement for cookie sessions is a common and almost standard approach. To summarise my position: |
Sure.
This is the same for session cookies, JWT-containing cookies, and JWT tokens themselves - you only need to explicitly 'refresh' them if they are about to expire. There's no difference here.
Users that block cookies will almost certainly also block Local Storage and other persistence measures (for precisely the same reason they block cookies). Privacy extensions do the same. Again, "JWT vs. cookies" is not a valid comparison, and if a user blocks cookies, then you will not be able to persist a token anyway. JWT or not, doesn't matter. (If a user blocks cookies wholesale, they already choose not to have data persistence anyway, so trying to support authentication for cookie-blocking users is a bit of a lost cause. That's the tradeoff that comes with it, and it's a completely technically reasonable tradeoff.)
See the edit of my previous post (third paragraph), which addresses single-use tokens in distributed architectures. These aren't sessions nor should they be persistent, so the issues I've described don't apply there.
OAuth makes use of single-use tokens. It's not a replacement for sessions. Again, see the edit of my previous post.
They can't. You still need to obtain a JWT somehow, which means it needs to be issued by the server, which means you need to ask the server for it. Whether the server returns a cookie or a different header or value doesn't matter. And again, "cookies vs. JWT" is not a valid comparison.
Not seeing an argument here.
This is a non-benefit - you don't need the token until you intend to communicate with a server anyway, so you can just attempt to make a request and deal with the 403 when it happens. Trying to avoid asking the server for something that inherently involves talking to a server (namely, making an authenticated request) doesn't make sense. Not to mention that, if you want to know ahead of time whether your session will have expired, you can just send a separate cookie for this. Since it's just a UX hint for the application, you don't even need to verify its authenticity - and you need to deal with unexpected authentication failures anyway due to clock skew and changed signing keys.
It doesn't. Any reasonable HTTP library - browser or not - will support cookies. Cookies are by no means exclusive to browsers, they're a HTTP feature like any other.
I still haven't seen any concrete examples of such 'flexibility'.
That's a very ambiguous statement. You're comparing using JWT as part of the solution, to using session cookies as the entire solution. These are not opposites - many complex architectures will require a combination of both session cookies and single-use JWT tokens, for example for SSO systems or distributed architectures.
No. JWT tokens are a last resort when you cannot meet the requirements with session cookies.
Technically correct.
It is the only usecase that I am aware of, and I have not seen any other valid ones mentioned throughout this thread. Mind that I am talking specifically about stateless sessions, not about stateless tokens in general. |
I ask you this - how do I deploy an application that uses 3 different services ( perhaps on different container infrastructure etc ) and integrate them into the app relying on session cookies? If I setup an auth service and wish to decouple it from another service is the best approach to run a shared proxying cookie session handler? Is this an edge case? |
Depends on what the 3 services do. Can you elaborate?
You'd have the auth service issue a single-use JWT token indicating successful authentication, optionally including 'profile information' for the user, depending on your architecture. Then, depending on the application:
In both cases, the JWT token will only be valid for something like 5 minutes (to account for clock skew), and used once - to exchange it for a session on the application server. If you include profile information in the token, the authentication service remains completely decoupled from the application. EDIT: Added standalone application case. |
Lets assume we are in SPA / Hybrid mobile app development scenario. Also assume that we are just using JWT for session - not OUATH with auth and bearer tokens - just login and receive bearer token. As an example lets say I've created an AWS service with a graph query service, a mapping or GIS service on a docker rackspace and a REST interface to postgres db to manage user profile data. I can use the same JWT in header requests to all REST services and validate against a common secret to have shared validation from the JWT issued once. Lets say they all require reasonable confidence that the user is who they say they are. If I understand correctly in your situation I've got 9 requests bouncing around every period instead of 3. I've got an auth server being wacked to confirm established sessions. I've got more code and more moving parts. I get the advantage of being able to terminate the sessions each period but what if that isn't a requirement. What if I don't care about receiving posted data for another 48 hours after the user has been terminated and using the auth server for new requests I can still filter out what I don't need? In this use case, minor time skew is irrelevant because of the session granularity being set appropriately and as with session cookies I would implement the client refreshing the JWT through the auth server in the appropriate timeout period. As far as 'profile' goes lets just stick with a share uid as the common id ( if I understand correctly ) and the server side implementations contain a shared secret for signing/validating the JWT. In my proposed architecture I do not need to revoke the tokens at a finer granularity than provided by the JWT timeout so why should I use session cookies instead? If I align with your proposed architecture then I indeed need to grapple with the timeouts across multiple cookies. As an example if the client logs in and receives an auth'd session cookie that expires in 1 hr I could discuss approaches to stale data but the problem scope in this use case does not rely on invalidating stale credentials ( from perspective of the auth server ) so this would not be relevant. It is my understanding is that we are discussing your assertion that using JWT as an authenticated session management approach is inherently inferior and incorrect versus the use of session cookies as an authenticated session management approach for cross domain services within a hybrid mobile application to be run on devices intermittently without resupply of credentials. I am trying to ascertain whether you would argue that the proposed approach is inherently less secure or less 'correct' in any way. As I see it there are significant advantages in the simplicity of this architecture and no advantages offered by the heavier more complex solution required to manage sessions across all the services that have not been accounted for and traded off for the simpler architecture. If you could point out how this solution would experience problems not experienced using cookies to manage sessions then it would really help me to underdtand those explicitly ( ie how is the security compromised ) |
There's a difference between stateful and stateless services.
This is describing how you'd solve the problem, not what the problem is. It's not useful when asking me to explain how to approach it with sessions, because it already assumes that you won't be using sessions. Describe the problem instead.
You can't.
Unlikely. See my remark about stateful vs. stateless services.
Authentication and session management, especially in distributed architectures, is complex. There's a reason engineers have avoided distributed architectures wherever possible in the past. "Just use JWT" glosses over this and pretends it's easier than it really is, by completely ignoring data staleness and session invalidation. The security holes are there, and I've made several attempts at explaining them - that you can't clearly see them is not something I can do anything about, if you don't ask specific questions about the parts that are unclear to you.
In the example I gave? Because they are intended as single-use exchange tokens, not persistent identifiers. You don't want them to be persistent identifiers, because you can't revoke them.
There's no risk in refreshing a session.
They are just as important a part of a robust authentication system as all the other points mentioned. Ignoring them is not an option. And again, this is not about "cookies", this is about sessions. For sessions, no, the same issues do not apply; a centralized/stateful session store means data doesn't go stale at all and profile information can be retrieved at any point, and clock skew is an issue for any limited-validity tokens that are exchanged between different systems. |
It looks as though we could summarise your objection to JWT as a session management approach could come down to you attachment to a definition of sessions that requires revocation per request (and a few other features that have traditionally been part of ensuring that a user is authorised to access) and the danger associated in refreshing them (if they are intercepted) . Distributed processing is the new norm - multiple services is very common - if we are to adopt the use of this kind of approach to multi-service architecture then we need to fully understand the consequences. Distributed databases have existed for a long time. Distributed data stores such as DNS have existing since the beginning. Sometimes the simplicity of the architecture affords more benefits than trying to squeeze the existing dominant standard beyond its design limits. If we are aware of the transactional ACID issues in our service request sessions then there is no reason we shouldn't embrace a JWT session management approach to authenticat services to fully exploit the possibilities without being constrained by what quickly becomes a complex infrastructure if we insist on hard constraints and try to shoe-horn session cookies as the solution that is superior. The use of JS as a dependency is pretty minor - in the context of hybrid mobile SPA it is unlikely you are needing to accomodate a JS free client. Suggesting that this is an issue whilst similarly claiming that redis provides an efficient option for session storage seems a little contradictory. |
My original reasoning for using a JWT as the Token for authorisation is that verifying a JWT is CPU-bound (my "old" laptop can verify 180k JWTs per second) by contrast if we were to use a simple token and have to look it up in memory (or a Database) the operation would be I/O-bound (or worse Network-bound) which would be considerably slower. Our Session management system first checks that the JWT is valid by verifying that it was signed using our key - and rejects a message early if it was not - and then checks if the session has not yet been invalidated (e.g. by the user logging out). I know JWTs might not have been designed to be used as the tokens in Authorization headers, but I don't think I fully understand why it's a "bad idea" given that's faster than other session-management systems...
|
I'll address the problems one by one:
This is not inherently desirable. Cookies exist for a very specific purpose, and work well for that purpose.
This is not how the e-Privacy Directive works. Technically necessary sessions (ie. not for analytics/tracking/etc., but for keeping track of an account or similar tasks) do not fall under the consent scheme to begin with.
Similarly, cookies are not explicitly mentioned in the Directive anywhere, nor is it intended to refer to them - any kind of persistent identifier stored on a user's system by your application for non-essential purposes falls under the Directive, and that includes a JWT stored by some other mechanism.
This is misleading. 'Stateless sessions' introduce many new issues, both security-wise and otherwise, for example:
... all the while 'solving' a problem that almost nobody actually has - in 99.99% of cases, you don't need to statelessly scale your sessions.
There are many simpler techniques such as running a dedicated and vertically scaled session storage server (eg. using Redis), 'sticky sessions', geographically clustered session servers, etc. Unless you are running at the scale of eg. Reddit, you almost certainly do not need stateless sessions.
This is an unbelievably misleading and harmful statement. JWT is not CSRF mitigation. You have roughly two choices for working with JWTs:
Fundamentally, JWTs are not for sessions - rather, they are primarily for transferring claims through an untrusted third-party, while preventing tampering.
At the very least, the entire "Why?" section needs to be removed (as it's simply wrong and provides harmful advice), but frankly, since it's the premise of the entire repository, I feel like the existence of the entire repository should be reconsidered. It is seriously irresponsible to give developers harmful advice like this.
The text was updated successfully, but these errors were encountered: