Readit News logoReadit News
StevePerkins · 8 years ago
The criticisms of JWT seem to fall into two categories:

(1) Criticizing vulnerabilities in particular JWT libraries, as in this article.

(2) Generally criticizing the practice of using any "stateless" client tokens. Because there's no great way to revoke them early while remaining stateless, etc.

The problem is that both of these groups only criticize, neither of them can ever seem to actually recommend any alternatives.

I could care less about JWT per se. I'm happy to implement a similar pattern with something else (e.g. store a secure cookie post-auth, skip all the refresh business and just let it expire when it expires, and employ an ugly revocation strategy only if absolutely necessary). I don't need JWT for this.

If I'm providing a REST API, then I'd prefer a token string that I could pass as a header value rather than forcing the use of cookies. Although I suppose you could argue that a cookie is just another header value.

Either way, if you're serving up a REST API to a JavaScript UI... what's NOT a good option is server-side session state (e.g. Java servlet sessions). That requires you to either: configure your load balancer for sticky-sessions, or employ a solution to share session state across all your server-side instances (which never works very reliably). Moreover, relying on a session isn't a very RESTful auth strategy in the first place.

So if I'm writing a SPA in 2017, then I'm definitely taking a client-side approach and running afoul of the #2 critics. And since JWT is so widely implemented (e.g. if I use a "Login with Google" option then I'm using JWT), I'm probably running afoul of the #1 critics too.

These criticism are fine, I guess. There's no faster route to blog clicks, book sales, speaker invites, and consulting dollars than: (1) telling everyone to jump on this year's hype train, or (2) telling everyone that last year's hype train sucks. What the world really needs is a bit more actual prescriptive recommendations of what to do instead.

tptacek · 8 years ago
I don't care if you want to use stateless client tokens. They're fine. You should understand the operational limitations (they may keep you up late on a Friday scrambling to deploy a token blacklist), but, we're all adults here, and you can make your own decisions about that.

The issue with JWT in particular is that it doesn't bring anything to the table, but comes with a whole lot of terrifying complexity. Worse, you as a developer won't see that complexity: JWT looks like a simple token with a magic cryptographically-protected bag-of-attributes interface. The problems are all behind the scenes.

For most applications, the technical problems JWT solves are not especially complicated. Parseable bearer tokens are something Rails has been able to generate for close to a decade using ActiveSupport::MessageEncryptor. AS::ME is substantially safer than JWT, but people are swapping it out of applications in favor of JWT.

Someone needs to write the blog post about how to provide bag-of-attributes secure bearer tokens in all the major programming environments. Someone else needs to get to work standardizing one of those formats as an alternative to JWT so that there's a simple answer to "if not JWT then what?" that rebuts the (I think sort of silly) presumption that whatever an app uses needs to be RFC standardized.

But there's a reason crypto people hate the JWT/JOSE/JWE standards. You should avoid them. They're in the news again because someone noticed that one of the public key constructions (ECDHE-ES) is terribly insecure. I think it's literally the case that no cryptographer bothered to point this out before because they all assumed people knew JWT was a tire fire.

Alex3917 · 8 years ago
> they may keep you up late on a Friday scrambling to deploy a token blacklist

Because every token has an iat datetime, you don't need a token blacklist to invalidate tokens. You just need some sort of tokens_invalid_if_issued_before_datetime setting that gets checked whenever you validate the signature of a token.

The alternative is to store a UUID for each user, and just rotate those whenever they log out, change or reset their password, or there is some sort of security event. These are then stored in the payload and used as a secret. The one advantage over just using dates is that with the former, there can be weird bugs if you have multiple servers with clocks that are out of sync.

But you shouldn't ever need to blacklist specific tokens, at least not unless you have some highly specialized use case.

bgentry · 8 years ago
Assuming that:

- your JWT libraries don't do anything dumb like accepting the `none` algorithm

- you're using HMAC SHA-256

- your access tokens have a short (~20 min) expiration time

- your refresh tokens are easily revocable

Can you elaborate on the specific security advantages that a token encoded with ActiveSupport::MessageEncryptor would have over such a JWT implementation?

Why do you think there aren't more AS::ME implementations out there if it's a superior solution? I only know of a Go implementation and haven't seen others: https://godoc.org/github.com/mattetti/goRailsYourself/crypto

Edit

I saw you mention Fernet in another comment. As a Heroku alum I'm quite familiar with Fernet (we used it for lots of things), but to my knowledge those projects are on life support at best.

theptip · 8 years ago
I appreciate that this comment is wise from a cryptosystems perspective, i.e. there are a number of ways to do JWT wrong, not enough safety guards, etc., but is there not a subset of JWT that is safe to use?

The OP article makes it sound like it's impossible to use JWT correctly, but I was under the impression that if I 1) am the issuer, and 2) I hardcode a single algorithm on my API endpoints, that neither of the issues in the OP apply. (The EC issue would apply if that algorithm was chosen).

Is there a safe subset of JWT? And isn't there value to small players in using the safe subset of JWT which is battle-hardened by guys with big security teams like Google?

fovc · 8 years ago
It's not that need an RFC standardized solution for everything, but I'd rather not roll my own anything related to crypto. Would something like crypto_auth(json(bag)) be better here? (crypto_auth from libsodium, json being sorted without whitespace)
scottmf · 8 years ago
> there's a reason crypto people hate the JWT/JOSE/JWE standards. You should avoid them

Could you give more info about this? If ECDHE-ES is avoided why else is JWT insecure?

mst · 8 years ago
Seems like, practically, that suggests three options:

1. Take something like AS::ME that already has real use and implement it for as many platforms as possible

2. Define a really restricted subset of JWT (which may be necessary anyway for purposes of saying to management "yes, we're buzzword compliant")

3. Invent a non-AS::ME "bag-of-attributes secure bearer token" system and implement it everywhere.

I think part of the trouble with 3 is that people like me genuinely worry that if we tried to roll our own we'd manage to do worse than JWT in spite of JWT being terrible.

So maybe step zero is for somebody with crypto knowledge to explain one sane way to do the "bag-of-attributes secure bearer token" part ... or you to point the audience to a blog post that already exists that describes it, because, well, because I suspect quite a few of us trust you to say "this post actually describes a sensible plan" while we don't trust ourselves to be able to tell.

tracker1 · 8 years ago
For my service to service requests, I tend to require the token itself be set to an expiration of less than 1 minute from creation. I actually code 2min in the check, but document 1 for access clients. This allows for more than enough drift and with https mitigates the level of risk for replay attacks.

Beyond this a header/signature for the body/payload will reduce the risk of the rest.

As to being able to select the signature algorithm, or set the uri for the public key... ignore this, or whitelist domains or methods. Yes, there's some wholes regarding a "by the books" implementation... that doesn't mean you need to support the entire spec.

I implemented about 1/2 the SCORM spec in an API once, and it was 8 years before a specific course needed a part that was missing. Yes, it isn't 100% compliant, but if it does the job, and is more secure as a result, then I'm in favor of it.

asanso · 8 years ago
It seems that Matthew Green warned them about some of their choices though back in 2012!! https://www.ietf.org/mail-archive/web/jose/current/msg00366....
danjoc · 8 years ago
>that rebuts the (I think sort of silly) presumption that whatever an app uses needs to be RFC standardized.

I thought crypto mantra was "Never roll your own." An RFC (Request For Comments) is a literal attempt to follow that advice by seeking the advice of cryptographers who are presumably smarter at coming up with crypto standards. Where were the cryptographers during the draft phase when comments were being solicited?

>I think it's literally the case that no cryptographer bothered to point this out before because they all assumed people knew JWT was a tire fire.

Oh. Cunningham's Law. You know, if you're not part of the solution, you're part of the precipitate.

That's some considerable JWT fallout, since companies making a business out of security are endorsing it. Auth0 for example, https://auth0.com/docs/jwt

Until I read this article, I was under the impression JWT was the best new thing.

lr4444lr · 8 years ago
Either way, if you're serving up a REST API to a JavaScript UI... what's NOT a good option is server-side session state (e.g. Java servlet sessions)

Can you explain what you mean, as oppose to other kinds of session tokens?

Roy Fielding makes it abundantly clear[0] in the seminal delineation of REST that

  We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.
This has given me pause to doubt just how many people are really implementing REST, and/or how useful a model it is in modern web applications.

[0]https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...

throwaway2016a · 8 years ago
> This has given me pause to doubt just how many people are really implementing REST, and/or how useful a model it is in modern web applications.

Not many. I've made a good career out of consulting people who are doing REST wrong :)

Usually they are either storing state or forgetting about HTAEOAS (Hypermedia). Often they are also negotiated format and version incorrectly and in a way that doesn't scale.

meric · 8 years ago
IMO sessions for authentication is fine as long as we don't store any session variables. In the end someone's going to be keeping track of the number of GET requests made by each API consumer on each endpoint, and practically it's not breaking REST as long as that state doesn't affect the information GETable by the client.
Chris2048 · 8 years ago
So, does this include web tokens too, or is auth a special case?
jv22222 · 8 years ago
On another note.

Dear Americans, the queen would like you to stop saying "could care less" - by David Mitchell of Peep Show

https://www.youtube.com/watch?v=om7O0MFkmpw

eric_the_read · 8 years ago
I could care less about this request, but I can't be bothered to make the effort.
nocman · 8 years ago
I am American, and I'm sure this bothers me more than it actually bothers the queen.

Between that and the incessant use of the incorrect phrase "for free" instead of the correct phrase "for nothing" it's amazing that I can stand to read anything on the internet.

xD

jchw · 8 years ago
What's difficult about setting up a Redis cluster to back sessions? Yes, it adds a point of failure... so does having a database of any kind. However, I'd hardly call it difficult. If you're on Amazon, you can just create an Elasticache cluster and not even concern yourself with the ops.

I don't hate secure cookies or anything, but some people act like plain-old regular cookies haven't been thoroughly solved by this point.

Related: Something people get wrong a lot with secure cookies is worrying about obscuring the cookie more than securing it. Encryption does not give you authentication; you need MAC for that. An encrypted message can still be blindly modified. Imagine being able to change a UID stored in a "secure" cookie even if you couldn't 100% control which. Eventually, if you try enough permutations, you're going to escalate your privileges!

jdmichal · 8 years ago
Nothing's difficult about that. But that doesn't mean that it's a good idea. How about distributing a signature and encryption key to all your servers, and using them to secure the outgoing and verify the incoming tokens. If you want easy, that's probably even easier than setting up a Redis store and tying your services to it.

Need an emergency revoke of every token? Easy: Replace your signature key. Any older token will fail signature verification. In which case, your system should require authentication and then generate a new token with an updated signature.

batoure · 8 years ago
Here is the use case that lead to the first implementation of JWT I was ever part of.

You have a single page webapp that uses two APIs for part of the application. For security reasons the APIs are zoned in such a way that neither of them can communicate with each other. The machine of the user sits in a zone where it can send HTTP requests to the zones of either API.

Now design a way to manage sessions across both APIs...

There are certainly a number of ways to accomplish this, but JWT was the cleanest and most performant.

chmike · 8 years ago
When the authentication info needs to be used with servers in different location of the world, JWT is better. Getting the session info from a redis server or something equivalent isn't free. Deciphering a JWT token may be faster. So, the most appropriate method depends on the use case.

If all the servers are in one location, a random byte sequence as session id key with cached info is the most simple, compact and efficient.

stephenr · 8 years ago
The problem is you're suggesting real-world, ops-capable solutions to a problem "Devops" (as in, developers can do it, we don't need ops) people don't want to understand because they'd rather jump on yet another poorly designed "solution" to a problem they don't really have.
tracker1 · 8 years ago
JWT signature verification usually takes less time than the network request to a redis server... assuming it's non-local, because HA.
jdmichal · 8 years ago
I can make an attempt at an alternative:

Distribute signing and encryption keys to all servers. Have them encrypt and sign the outgoing serialized token, whatever that consists of. Have them verify and decrypt the incoming token. This is just straight-forward cryptography, with keys known only to the server, so I'm pretty sure you won't get any arguments from (1). (And, I suppose the encryption could even be skipped, if you don't care that the internal format of the token is known.)

Emergency revocation of all tokens [0] is simply rotating the signing key. All tokens issued prior to the rotation will fail verification with the new key. That should trigger the authentication process, which will issue a new token with the updated key. This solves the revocation issue present in argument (2).

[0] Any other form of revocation is, in my opinion, not distinguishable from having server-side state. If you have to keep a list of bad tokens, why not just keep a list of the good tokens instead... And then it's only a short hop to the token being nothing but a key to lookup the full session state on the server.

deepanchor · 8 years ago
This is exactly the solution I use. I use a secret server (Vault, using Consul as a backend) to securely distribute and manage the encryption keys.
tracker1 · 8 years ago
And if you want to be able to authenticate users to a service that you do not want to send private keys to?
batoure · 8 years ago
You do understand that this is fundamentally the exact underlying mechanic of JWT?
mgkimsal · 8 years ago
> If I'm providing a REST API, then I'd prefer a token string that I could pass as a header value rather than forcing the use of cookies

Aren't cookies just strings passed as HTTP headers?

meric · 8 years ago
I hope someone can explain to me in practical terms difference between a session cookie string on a request and a token as header value.
Ajedi32 · 8 years ago
The very next sentence:

> Although I suppose you could argue that a cookie is just another header value.

So... yes.

batoure · 8 years ago
I grow more and more tired of posts touting engineering sensationalism.

Here is a point of order for developers who work on something realize it isn't idiot proof (them proof) out of the box and then want to write a sensational post:

Implementation and design are a core part of anything you do and considering the risks and accounting for them are part of doing business.

Having worked with large organizations that do active and passive scanning of the web I am constantly shocked how often we are contacting someone about basic SQL injection in their application... in 2017.

JWT is an incredibly powerful standard if implemented effectively but its not for the LAZY, it requires thoughtfulness where ever it is active.

JWT solves a serious and real problem that organizations face at scale which is why you see it implemented in systems like google sign in. Realistically its not going anywhere.

People love criticizing the movement towards stateless tokens on the web I find it pretty funny... crawl down the stack from their webheads and you usually come face to face with Kerberos managing auth within their networks...

tboyd47 · 8 years ago
The article very clearly is about the standard, not a particular JWT library.

Server-side session tokens stored in the database worked fine ten years ago, and they work fine today. No need to muck with the load balancer.

Stateless tokens are great too, and use two-factor auth when you need that extra layer of security. No need for newfangled standards; HTTP Basic remains a simple and effective way to convey that token.

tracker1 · 8 years ago
Except there are now many instances where no single database server can keep up with request load. It's not fine in all cases today. Where I work now a single request from the user goes into a pipeline of requests (some can be parallel, others not)... our SLA is X, everything that adds up to the total request time counts. Adding even 2-3ms for each service layer to verify session keys is too much.

This is as opposed to < 0.1ms for verifying a JWT. JWT is a structure for stateless tokens... once you have a token, what does 2FA add? nothing. Also, some algorithms are insecure, so don't use them, or blacklist them... Or, better whitelist the algorithm you do use.

gregpardo · 8 years ago
For number 2, you could expire them by encoding some identifier based off a hash or key tied to the user object. Change that object and have the server reject the token if that meta data no longer validates.
tracker1 · 8 years ago
Or have really short lived tokens, requiring regular refresh, and don't worry about expiring them... you can then delete the refresh token so it can't be found requiring full re-auth if necessary.

OAuth2 + JWT is fine... just whitelist the algorithms you allow and use HTTPS for all communications, even internal.

meddlepal · 8 years ago
I feel like the argument against #2 is usually purely hypothetical in nature. I really do not have a problem maintaining a small lookup cache for revocations. I feel like the argument against doing this tries to take the form of all server-side kept state is bad when in reality it's sticky state and huge object graphs (read: memory consumption) that get stuffed into session objects that are the real evil.

A server with 1GB can hold a lot of JWT's in memory. Probably more than most of the people building services here have to actually deal with.

falcolas · 8 years ago
Sure, revocation lists are relatively small. But they need to be available to every server (replication), be proof against server/service restarts (durable), and checked with every request (highly performant). So, a good revocation list effectively requires a database. Not a trivial thing to implement yourself, and a weighty requirement for an otherwise stateless service.
elithrar · 8 years ago
If you go so far as to maintain a revocation store that is checked on each request, you might as well just use that same store for full-blown server-side sessions.

By your measure, 1GB can store a lot of tokens in memory: 32B tokens + that again as metadata (e.g. user ID + TTL in Redis) = 15,625,000 tokens.

tracker1 · 8 years ago
Or better, have a really short lived requirement for server-server jwts (I suggest even 1m, having a new one per request).

For client-server a 5 minute refresh is fine, as long as you do a lookup for refresh, so you can expire refresh tokens, requiring a full re-auth.

lobo_tuerto · 8 years ago
I found this video incredibly informative about how to effectively implement JWTs, along with security advice and a nice refresh-reissue process:

https://youtu.be/mecILj3p4VA?t=2m8s

CiPHPerCoder · 8 years ago
> (1) Criticizing vulnerabilities in particular JWT libraries, as in this article.

The purpose of this article it criticize the standard, not particular libraries.

akfish · 8 years ago
I don't see any valid arguments in the post. The issues raised are either mis-implementation or misuse of JWT. All I am getting is "JWT can be misused in such such way that makes your application vulnerable. And neither its standards nor libraries prevent that, so it sucks".

But when is the last time we see any technology successfully prevented people from being silly?

sgift · 8 years ago
> But when is the last time we see any technology successfully prevented people from being silly?

You can never stop someone sufficiently motivated to shoot himself in the foot from doing it. But you can make it harder for those who would do it be accident by providing more safety features - in case of security this is usually seen as a good idea (safe defaults etc.)

revelation · 8 years ago
But this is the biggest thing with any security-sensitive code or practice!

Do not give people options, do not allow algorithmic flexibility, do not have fallbacks, do not have backward compatibility, do not allow "testing" or "insecure" options, do not have complex state machine behavior.

All of these things are exactly what JWT or other "design by commission" standards like SSL suffer from and they have predictably lead to ongoing, at times unfixable security problems.

ponytech · 8 years ago
I agree. I've read the whole article and still wonder why I should stop using JWT.
slau · 8 years ago
You shouldn't. Simply check that the hash algorithm specified by the client is the one you used when issuing the token. In a side project, I simply hard code the algorithm [1].

[1]: https://github.com/teotwaki/grace-calendar/blob/develop/app/...

Edit: DYAC.

nallerooth · 8 years ago
+1. I read the article and ended up with a TLDR where I expected some explanation and facts.

It's a good thing that cookies have never been used in a bad manner. /sarcasm

scandox · 8 years ago
I use stateful JWTs for session management, storing them in localStorage. If someone can exfiltrate the token, they will get a week long authorization, as well as some identifiable information (username, name and role).

Probably I can achieve the same overall system with cryptographically secure session cookies, that are persisted in a database, or other store that is accessible across multiple servers. I guess it would amount to the same thing.

Originally I implemented it because:

* My systems are SPA's. Totally JS dependent from the word go.

* I felt like there would be some advantages to being able to establish certain claims without verification. Say for display purposes prior to server comms (show a list of multiple available sessions for example)...In practise this hasn't really been true. Generally I find in the end I am always checking and verifying anyway - without any huge overhead.

* I've always had a sort of fuzz of uncertainty about Cookies. They always felt a bit out of my hands. Thinking it about rigorously of course, people can switch off JS. They can switch off persistence.

* All my user's local data can be persisted in one place, rather than having to store a reference in the Cookie and then lookup in localStorage. In reality though the code for this is pretty trivial...

So overall while I don't know how right he is, I feel like maybe he has a point. Why not just use cookies?

Maybe it's just because as a JS dev, I want everything to stay within a JS universe...and for some reason Cookies have always felt outside of that to me.

Klathmon · 8 years ago
If I can offer some advice in the other direction, don't use cookies.

I tried to do the right thing, use HTTP-only cookies set over an HTTPS endpoint only to find that it's stupidly complicated and has a lot of annoying edge cases. Turns out iOS's webviews don't like them, iOS in general doesn't like them to be on api.hostname.com if the app is on app.hostname.com, you can't validate if you are logged in or not without doing a web request (which is annoying as hell if you are trying to keep a "logged in" state in something like a react app), you need to deal with a bunch of stupid flags to get the damn browser to even let them go across domains, and a hell of a lot of other annoyances that I can't remember right now.

We are most likely moving to something like JWTs (stored in localstorage or indexeddb) soon because of these issues.

joepie91_ · 8 years ago
These "annoyances" are security features. They're there for a reason. Learn how they work and why they exist. Use them. Stop trying to treat them as bugs that you need to work around.
zepolen · 8 years ago
When you say validate login in a react app, what do you mean? Surely the only way to validate a login is to make a request. Or are you saying that your tokens never expire?
devdoomari · 8 years ago
well you can use JWT + Cookies... JWT request to https://api.somewhere.com/token-signin to get cookies for https://api.somewhere.com

(of course you 'can' but I'm not sure if this is recommended or not.)

cptskippy · 8 years ago
Wouldn't you need to assign your cookies to the TLD for them to be accessible to both subdomains?
maktouch · 8 years ago
That's weird. Cookies are part of the HTTP standard, no? That means iOS would be the one that is not respecting the RFC.

Kinda like Safari throwing exceptions when you're trying to access localstorage in incognito.

yarper · 8 years ago
Ideally you need to use httpOnly cookies to store your JWTs too.
ozim · 8 years ago
Can't you do "*.hostname.com" asp.net mvc handles it for me and I have subdomains for each customer and they log in and operate in their subdomain. All special cookie flags are configurable so it keeps top security. Getting cookies across domains is something you don't want to do, so I have kind of idea that maybe, probably you are doing something wrong.

My advice is "use proper framework".

lobo_tuerto · 8 years ago
Another advice: You shouldn't be saving the JWT on localStorage for security reasons, have a look at the info here: https://news.ycombinator.com/item?id=13866965
scandox · 8 years ago
Indeed the article in question links here as required prior reading: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...

So my comment was in the context of having read both of these. In the link here he also strongly argues against storage of JWT in localStorage.

throwaway2016a · 8 years ago
> So overall while I don't know how right he is, I feel like maybe he has a point. Why not just use cookies?

Because in a highly distributed system hitting a database to validate authorization is expensive and causes bottlenecks.

A cookie that requires you to hit the database does not solve that issue. Although if the cookie was signed some way that can be cryptographically verified then great. But then you are essentially re-implementing something you could be doing in a standard way instead.

lpa22 · 8 years ago
I think the expense of validating authorization to a database can often be worth the cost. Having a dedicated sharded SSD DB system, or other fast cached DB system that is dedicated to checking and validating a cookie/token of a user for each request solves many problems, such as quickly clearing tokens in the case of a hack, and if there is a DB failure on one of these systems then the user simply has to login again and their token/cookie will be stored on another DB in the shard.

The extra overhead on each request of checking these credentials, especially when these requests are hitting the product's database anyway, are often worth the additional security.

pilif · 8 years ago
cookies have one advantage over localStorage and custom headers though: They can be set by the server in a way that client-side JS code doesn't get to see or change them.

This makes abusing XSS vulnerabilities to get to the token slightly harder.

falcolas · 8 years ago
> Because in a highly distributed system hitting a database to validate authorization is expensive and causes bottlenecks.

Don't you have to do something similar to invalidate tokens anyway?

throwaway2016a · 8 years ago
I probably got down-voted because I conflated cookie with session token cookies. You can of course have a cookie that does not require a database lookup to validate.

But JWT takes care of having the expiry signed in the value (in a cookie the expiry is more of a suggestion that a modified client could ignore). Combine that with low expiry JWT tokens and high expiry refresh tokens (subject to more validation) I think it is a clear winner.

technion · 8 years ago
A lot of people are talking about the "none" algorithm issue, but the more recent vulnerability[0] is more telling: The report to the working group mailing list[1] led to the point that the standard had a "security considerations" section in the RFC, and this particular issue was never covered.

And now there are difficulties around the fact they cannot update an RFC which people will refer to for years.

It's not a vulnerability in one or two libraries - it looks like just about every made the same mistake, which points to something much more broken.

[0] https://auth0.com/blog/critical-vulnerability-in-json-web-en... [1] https://www.ietf.org/mail-archive/web/jose/current/msg05613....

jacopofar2 · 8 years ago
The "none" algorithm set in header is a well known problem and, for example, nodejs most used library automatically uses asymmetric keys when one is given, ignoring the header (https://github.com/auth0/node-jsonwebtoken/blob/master/verif...)

As long as the problem is known to the developers and the key is specified, I think the biggest issue of JWT is the lack of session invalidation (that is, if you log out your already emitted tokens are still valid until their expiration), but it's a good tradeoff for not having server sessions.

Freak_NL · 8 years ago
Session invalidation is possible though, by maintaining a (short) blacklist of tokens on the server. JSON Web Tokens can be given an ID (via the jti claim), and server-side these IDs can be matched against this blacklist. When you log out, you send a request to the service that your current token be blacklisted.

Because JSON Web Tokens are short-lived, the blacklist need only contain tokens valid for validity period plus a few seconds and remains very small (often empty).

If you use JWT to allow authorization on several server, then you do need to distribute this blacklist, so it is not a completely trivial solution. In the simplest scenario you might suffice with only maintaining a blacklist on the server that can refresh tokens (this means that when the token expires, a new one cannot be automatically acquired).

floatboth · 8 years ago
Yeah, and that's kinda sad because now you have to check a signature AND query a database!
_puk · 8 years ago
The none issue was highlighted by Tim McLean 2 years ago [0] and comes up in any trivial search about JWT. Surprised that anyone who chooses to use JWT is still getting caught by it as, as you say, any half decent library mitigates this.

For me, the log out / cross device session management issue seems to force a pattern of short expiry with self refreshing tokens. Commonly used devices feel always logged in, whereas uncommonly used devices end up needing a fresh log in each time.

0: https://www.chosenplaintext.ca/2015/03/31/jwt-algorithm-conf...

kierenj · 8 years ago
In terms of invalidation, I think a case-by-case basis is best, as it often is.

For example -

If some critical part of your app depends on a user's account or session being still valid, just do the check on that endpoint call (grab the sub/ID claim from the JWT and hit the DB, or similar).

The rest of the time - viewing stats/feed/whatever, admit that if the user had a valid token issued to them 5 minutes ago, it's probably OK to send them stats without having to check revocation (or whichever benefit of JWT you're exploiting).

Thing is, this at least gives you the /option/..

StreamBright · 8 years ago
Exactly. The session invalidation has to happen using a session store or expiry header or something similar. In this regard JWT is not better than cookies.
throwaway2016a · 8 years ago
> expiry header

JWT tokens have the expiration date embedded in the token. There is no way to force it to expire like you you can with cookies.

Although force is a strong word. Even with cookies if you tell the client to delete a cookie it doesn't mean it has to listen.

batoure · 8 years ago
session invalidation is actually very easy to implement. Its important to think of it as a process instead of a builtin to the standard.

In most of our implementations we achieve this by differentiating between the session token and a request token. Requests that actually power the app use tokens that are very short lived. Request tokens are generated by the core auth server using the session token. A session can be invalidated at the core auth server which will then refuse to give request tokens to the bearer.

cptskippy · 8 years ago
Session invalid is an issue with all Tokens.
camdenlock · 8 years ago
Oh my god! Outrage! Superlatives!

Come on. By all means, criticize flawed implementations containing bugs and security holes, but drop the attention-seeking behavior of screaming loudly about how an entire standard is [insert string of superlatives here related to "worthless" and "broken"]. If you're going to make such incredibly strong claims, your arguments had better be up to snuff.

With good implementations (plenty of which exist), and careful usage (via good coding and design habits), JWT is a fine standard and it can save a solid amount of time when constructing the security portions of a system.

Shouting about how something is 100% flawed and should be cast into the flames may get you plenty of views and outrage cred, but (thankfully) it doesn't say much about the veracity of your analysis.

davewritescode · 8 years ago
This article is slightly misleading. One should ALWAYS be suspect of any article that states X is always bad and should be avoided. Google, Facebook, Microsoft and hundreds of other companies are using JWT in security critical software. If you've ever logged into an app with Google, you've used JWT.

All I see here is the author complaining about poorly implemented JWT libraries. It's not a problem with the spec, it's a problem with the implementation. XML-DSIG suffered from a number of similar issues and was arguably less secure than JWT because of the massive attack surface provided by all the specifications layered on top of each other.

Here's how you can use JWT Safely:

1. Standardize on what's allowed in the alg header and validate it, don't rely on the JWT library you're using to do it for you.

2. Make sure you're using a high quality JWT library, jwt.io keeps a list of JWT implementations and highlights gaps.

3. Understand that bugs in code related to token generation and verification can and lead to compromise of your application and potentially your user's data. Treat such code with great care.

iofiiiiiiiii · 8 years ago
It would really help encourage the uptake of better alternatives like libsodium if it were standardized. Just referencing some random library can scare decision makers; whereas referencing an IETF official document or ISO standard makes them just take it as given.

The same problem exists with serialization formats - you have XML and JSON, both of which are standardized and have an "official face", although JSON was not born that way. Google protocol buffers are quite superior in many ways, yet as they are just some product of some company and not an actual standard, decision makers are scared of them.

Technology experts do not get to make all the technical decisions, so standardization matters, even if for the stakeholder feelgood factor!

keithwhor · 8 years ago
... yes, but... sidenote, JSON is almost unreasonably easy to grok, and translates well into every web-abstracted language, making it the clear-and-away winner.

At the end of the day, tech doesn't win. Developer experience wins. By the time companies have the resources to fight for every iota of performance, they've already won because they shipped product faster than everyone else --- why? Their developers could move and iterate quickly.

Deleted Comment