In cryptography, we have a concept of "misuse resistance". Misuse-resistant cryptography is designed to make implementation failures harder, in recognition of the fact that almost all cryptographic attacks, even the most sophisticated of them, are caused by implementation flaws and not fundamental breaks in crypto primitives. A good example of misuse-resistant cryptography is NMR, nonce-misuse resistance, such as SIV or AEZ. Misuse-resistant crypto is superior to crypto that isn't. For instance, a measure of misuse-resistance is a large part of why cryptographers generally prefer Curve25519 over NIST P-256.
So, as someone who does some work in crypto engineering, arguments about JWT being problematic only if implementations are "bungled" or developers are "incompetent" are sort of an obvious "tell" that the people behind those arguments aren't really crypto people. In crypto, this debate is over.
I know a lot of crypto people who do not like JWT. I don't know one who does. Here are some general JWT concerns:
* It's kitchen-sink complicated and designed without a single clear use case. The track record of cryptosystems with this property is very poor. Resilient cryptosystems tend to be simple and optimized for a specific use case.
* It's designed by a committee and, as far as anyone I know can tell, that committee doesn't include any serious cryptographers. I joked about this on Twitter after the last JWT disaster, saying that JWT's support for static-ephemeral P-curve ECDH was the cryptographic engineering equivalent of a "kick me" sign on the standard. You could look at JWT, see that it supported both RSA and P-curve ECDH, and immediately conclude that crypto experts hadn't had a guiding hand in the standard.
* Flaws in crypto protocols aren't exclusive to, but tend to occur mostly in, the joinery of the protocol. So crypto protocol designers are moving away from algorithm and "cipher suite" negotiation towards other mechanisms. Trevor Perrin's Noise framework is a great example: rather than negotiating, it defines a family of protocols and applications can adopt one or the other without committing themselves to supporting different ones dynamically. Not only does JWT do a form of negotiation, but it actually allows implementations to negotiate NO cryptography. That's a disqualifying own-goal.
* JWT's defaults are incoherent. For instance: non-replayability, one of the most basic questions to answer about a cryptographic token, is optional. Someone downthread made a weird comparison between JWT and Nacl (weird because Nacl is a library of primitives, not a protocol) based on forward-security. But for a token, replayability is a much more urgent concern.
* The protocol mixes metadata and application data in two different bag-of-attributes structures and generally does its best to maximize all the concerns you'd have doing cryptography with a format as malleable as JSON. Seemingly the only reason it does that is because it's "layered" on JOSE, leaving the impression that making a pretty lego diagram is more important to its designers than coming up with a simple, secure standard.
* It's 2017 and the standard still includes X.509, via JWK, which also includes indirected key lookups.
* The standard supports, and some implementations even default to, compressed plaintext. It feels like 2012 never happened for this project.
For almost every use I've seen in the real world, JWT is drastic overkill; often it's just an gussied-up means of expressing a trivial bearer token, the kind that could be expressed securely with virtually no risk of implementation flaws simply by hexifying 20 bytes of urandom. For the rare instances that actually benefit from public key cryptography, JWT makes a hard task even harder. I don't believe anyone is ever better off using JWT. Avoid it.
often it's just an gussied-up means of expressing a trivial bearer token, the kind that could be expressed securely with virtually no risk of implementation flaws simply by hexifying 20 bytes of urandom.
This should probably be the first thing anyone thinking of using JWT reads.
> For almost every use I've seen in the real world, JWT is drastic overkill; often it's just an gussied-up means of expressing a trivial bearer token.
This is certainly true for schemes that require trips to a source-of-truth database to authorize a token (c->auth, c->resource, resource->auth). It's also true for schemes where the token is associated with capabilities that are loaded from a database. Using JWT to implement RBAC is flawed.
However, there is a strong use case for the token carrying its own capabilities -- that is, a token that is more than just "20 bytes of urandom".
If a resource service can derive the capabilities associated with a token generated by a trusted authentication service without contacting that service, that has real world implications for lower latency, higher throughput applications that are simpler to compose and operate.
As far the cryptographic credibility, the idea behind capability-based security is an old one, and I'm sure you're aware of the research. This particular spec may be problematic, folks may be misunderstanding and misusing the primitives, but the underlying idea is sound.
I don't deny that capability tokens are useful; they certainly can be. JOSE is just a poor vector for getting them.
The issue isn't with capabilities, or delegated authentication, or public key tokens, or even standardizing any of those things. I think at this point I've been pretty clear about what I believe the issues actually are.
I was asking about standards for Web-based capabilities, delegated authentication, and public key tokens; not the individual message authentication or (a)symmetric encryption components.
Echoing tptacek's comment above: the problems with using those individual pieces is in the joinery - combining them in ways that are broken.
> JWT is drastic overkill; often it's just an gussied-up means of expressing a trivial bearer token, the kind that could be expressed securely with virtually no risk of implementation flaws simply by hexifying 20 bytes of urandom
Can you point us to an article showing how to implement this for a web app communicating with an API? Lacking crypto expertise and documentation, the average programmer is going to use something like Auth0, and if his users' recipes or jogging history is compromised, so be it.
"symmetric cryptography" is not mentioned in your article. And I specifically asked for example implementations, which is something Auth0 gives me for just about every platform. If your goal is to have programmers act on this information, the alternative(s) should to be as easy as the implementation you are moaning about. Especially when the claim is that JWT is overly complicated. Show us the simpler alternative, spelled out as well as the Auth0 team spell it out, and maybe us non-crypto experts will bite.
The protocol is complicated. It's evident to everybody that the library implementations are simple, which is why so many people with no background in cryptography have such strong feelings about JWT. We get it: they made it very easy for you to do the wrong thing, and you'd rather things stay easy. I sincerely sympathize with your problem. But it is a problem.
Thanks for recognizing no one (as far as I know) has made it easy to do the right thing. Yet. Since it sounds like doing the right thing might not actually be that difficult, why haven't market forces taken over? Since many are willing to pay for Auth0 services, why isn't there a similar product that isn't built on JWT and that gets the approval of the crypto community? I would pay for it. I bet others would. I want to focus on building my web app and API and the user experience. I don't want to have to worry that I've made a mistake with authentication, which is outside my area of expertise. I would bet that describes a huge number of programmers creating public facing apps.
Thanks for the example, but I don't use Go and don't plan on learning it just to understand how to switch from using JWT. I need an example for a React frontend consuming a nodejs API (that's just one example). I hope you're getting the idea that these many anti-JWT articles are strong on complaining but weak on providing a solution as well documented with examples as the Auth0 team has provided. Flawed or not, JWT is being used because there are parts (like sample code in many languages) of the JWT offering that are better than what's offered by an article complaining about JWT.
In general, implementing non-cryptographically-secure protocols is easier than implementing cryptographically secure tools; there are many ways to set up something insecurely.
I recently set up libsodium for a client running Node.js on the server, and could work on this for you as well, if you want to send me an email, I can send you my rates.
What's your value proposition? Auth0 works for me, has a free tier, and my users' data is not anything so private. On the server side I only accept the HMAC-SHA256 algorithm, negating your biggest concern about JWT. Perhaps, as you claim in your article, that "is not JWT". I'm ok with that. How would your services save me money or increase my profit? I would be far more interested in a freemium SaaS alternative to Auth0 that fixes the concerns with JWT than I would be in paying an individual consultant (who might or might not be a crypto / auth expert - hard for me to verify) and who could be hit by a bus.
I don't know, you asked about how this could be done, and I could build it for you.
My value proposition is I've shipped a lot of useful things for companies, and found security vulnerabilities, and those skills are in demand these days, I guess.
Well, what I asked for was an article showing how to do it in many languages and platforms. What I got was an offer to hire a high priced consultant. This is one of the reasons JWT and Auth0 are winning. I would love to do things the right™ way, and I appreciated your article. But there is a lot more the crypto community (or someone) needs to offer to make the alternatives to JWT just as attractive as JWT.
If you liked his article, as I did, what are we actually debating at this point? If all you're pointing out is that a single blog post hasn't solved the problem of JWT being promoted as a safe crypto standard when it isn't, well, everyone agrees on that already. Nobody has claimed this blog post to be more than it is: a good blog post.
Are we debating? I was trying to find a viable alternative to JWT that isn't "hire me at an expensive hourly rate". I think that's a pretty reasonable goal after reading yet another "don't use JWT" article, of which I've seen dozens in the past few years.
I only made the comparison with NaCl because the OP did (and used the wrong primitive) and brought up Forward Secrecy as a major flaw in JWT.
OP also mentioned JWT libraries ignoring embedded X.509 certificates as a problem if we're at it.
But you need alternatives.
NaCl is not alternative, because you need to base a protocol on top of that. Noise is not an alternative because it's not meant for the same purposes. Fernet is the only thing close to be an alternative, but it lacks useful features (for instance, how do you specify a key ID for key rotation), supports only symmetric encryption, has a weird cipher choice, and barely gets any library support.
In fact I do not need alternatives to the JWT standard. Part of my argument is that what JWT is trying to do --- providing one overarching standard for every conceivable token authentication use case --- is simply a bad idea.
Regardless, bad engineering is bad engineering. Bad security engineering gets people hurt. It's not that JWT doesn't do the best job it could do: it's that it's a snakepit of implementation traps that create vulnerabilities. For me, the argument ends there.
In fact, I think JWT is probably a classic example of non-cryptographers combining multiple proposals with different use cases into one standard. The others such as JWS and JWE are not as flawed.
So, as someone who does some work in crypto engineering, arguments about JWT being problematic only if implementations are "bungled" or developers are "incompetent" are sort of an obvious "tell" that the people behind those arguments aren't really crypto people. In crypto, this debate is over.
I know a lot of crypto people who do not like JWT. I don't know one who does. Here are some general JWT concerns:
* It's kitchen-sink complicated and designed without a single clear use case. The track record of cryptosystems with this property is very poor. Resilient cryptosystems tend to be simple and optimized for a specific use case.
* It's designed by a committee and, as far as anyone I know can tell, that committee doesn't include any serious cryptographers. I joked about this on Twitter after the last JWT disaster, saying that JWT's support for static-ephemeral P-curve ECDH was the cryptographic engineering equivalent of a "kick me" sign on the standard. You could look at JWT, see that it supported both RSA and P-curve ECDH, and immediately conclude that crypto experts hadn't had a guiding hand in the standard.
* Flaws in crypto protocols aren't exclusive to, but tend to occur mostly in, the joinery of the protocol. So crypto protocol designers are moving away from algorithm and "cipher suite" negotiation towards other mechanisms. Trevor Perrin's Noise framework is a great example: rather than negotiating, it defines a family of protocols and applications can adopt one or the other without committing themselves to supporting different ones dynamically. Not only does JWT do a form of negotiation, but it actually allows implementations to negotiate NO cryptography. That's a disqualifying own-goal.
* JWT's defaults are incoherent. For instance: non-replayability, one of the most basic questions to answer about a cryptographic token, is optional. Someone downthread made a weird comparison between JWT and Nacl (weird because Nacl is a library of primitives, not a protocol) based on forward-security. But for a token, replayability is a much more urgent concern.
* The protocol mixes metadata and application data in two different bag-of-attributes structures and generally does its best to maximize all the concerns you'd have doing cryptography with a format as malleable as JSON. Seemingly the only reason it does that is because it's "layered" on JOSE, leaving the impression that making a pretty lego diagram is more important to its designers than coming up with a simple, secure standard.
* It's 2017 and the standard still includes X.509, via JWK, which also includes indirected key lookups.
* The standard supports, and some implementations even default to, compressed plaintext. It feels like 2012 never happened for this project.
For almost every use I've seen in the real world, JWT is drastic overkill; often it's just an gussied-up means of expressing a trivial bearer token, the kind that could be expressed securely with virtually no risk of implementation flaws simply by hexifying 20 bytes of urandom. For the rare instances that actually benefit from public key cryptography, JWT makes a hard task even harder. I don't believe anyone is ever better off using JWT. Avoid it.