
Javascript Object Signing and Encryption is a Bad Standard (2017) - xenocratus
https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid
======
skrebbel
If you, like me, prefer HN comments over articles:

The author does not just complain about JOSE and JWT but he also designed an
alternative, PASETO: [https://paseto.io/](https://paseto.io/)

Here's a nice PASETO write-up from Okta, a reputable third party:
[https://developer.okta.com/blog/2019/10/17/a-thorough-
introd...](https://developer.okta.com/blog/2019/10/17/a-thorough-introduction-
to-paseto)

PASETO looks excellent to me, in that it's proper developer friendly and makes
it hard for non crypto nerds like me to shoot themselves in the foot. I can't
wait for it to replace JWT in popularity.

~~~
badrabbit
That's nice and all but standards exist for a reason. You ask devs to use it
in order to be compliant. Regardless of merits, you can't ask people who are
not knowledgable about crypto to use a library by some guy/corp just because
you think it has better merits. I mean, I guess you can and some will listen
but only a few. Most webdevs for non-web businesses are happy to go with a
standard so if something goes wrong they don't get blamed for picking it. And
many security/vulnerability pros agree with that line of thinking as well.

In practice,if paseto is better I think an internet draft is in order. If JSOE
is bad by commonly accepted security measurements then shouldn't the ietf wg
have a mailing list where these shortcomings can be discussed and fixed?

~~~
CiPHPerCoder
> In practice,if paseto is better I think an internet draft is in order.

[https://paseto.io/rfc/](https://paseto.io/rfc/)

~~~
badrabbit
It would be great if it at least becomes a draft. Did IETF simply ignore the
proposal since 2018?

~~~
CiPHPerCoder
No, it became a draft. It just hasn't become a RFC. See:
[https://github.com/paragonie/paseto/issues/108](https://github.com/paragonie/paseto/issues/108)

------
Diggsey
Great article and I agree with all of the criticisms.

There is a big problem with internet standards where the "division of thought"
leaves a gap in the middle. The standard author thinks "I am just designing a
template for people to follow, it's up to the implementor to consider whether
what they're doing actually makes sense for their use-case" and the person
implementing that standard thinks "I have implemented it exactly as described,
therefore all uses must be sane/secure/whatever".

For example, the HTTP signatures draft standard:
[https://tools.ietf.org/id/draft-cavage-http-
signatures-12.ht...](https://tools.ietf.org/id/draft-cavage-http-
signatures-12.html)

It specifies a pattern for signing and verifying HTTP requests. You can choose
what headers to include in the signature. Now "obviously" any implementation
of this standard should require you to specify up-front what headers clients
must include in the signature for a request to be valid, but the specification
does not mention this at all in the verification section, and none of the
reference implementations actually allow you to do this! So as an attacker, I
can craft any request I want and just tell the server "I'm not including any
headers in the signature".

Similarly: you can include the date header in the signature to help prevent
replay attacks, but nowhere does it say that you probably want to check that
the date on the request is actually within some threshold of the current time.

And again: you can include the message digest in the signature, but nowhere
does it say that you should actually verify that digest against the body.
Worse, message digests are an entirely separate spec and no constraints are
given about what digest algorithms should be used (many of them are not
designed to be cryptographically secure). On top of that, message digests only
make sense on requests with a body, so even if your library has support for
"require certain headers to be present", there is likely no way to only
enforce that a digest header is present for requests with a body.

~~~
philsnow
The "division of thought" you talk about is the opposite of "opinionated"
designs/standards.

The former assumes that the reader is going to take their time, think about
their own implementation and their own specific use case, and make several
careful decisions about how to make it work.

The latter assumes that ain't no reader got time fo dat, and is going to try
to npm install any packages that have the same name as keywords in the title
of your standard and assume that they're fine.

Development these days is unfortunately slanted towards the latter at a lot of
companies who only measure output on number of features you've shipped or the
impact of products you've launched, so every incentive there is to ship things
as soon as you can.

However, there's no field in package repository metadata that says "this
package has sharp edges, use with care" or "this package comes with safe
defaults, but use with care nonetheless".

~~~
kreetx
Not so sure - you can design things unopinionated but still have them secure.
As an analogy, the whole point of statical typing is to allow all sensible
programs to be written while keeping out everything that contradict itself.
I.e if the PASETO were a type and an implementation a program then you
wouldn't be able to write an implementation that would adher the type but
would be insecure. Doesn't appear to be so with JWT and co.

------
Autowired
> invites developers to come up with clever explanations and workarounds
> instead of careful engineering

I don't like the accusative tone when talking engineering. There are plenty of
good reasons not to use server-side sessions, including the need to replicate
them between nodes, or otherwise offload them to an external database, and if
you do it asynchronously you have to make your clients sticky. People use JWT
to achieve statelessness, which makes it easier to increase availability.

~~~
CiPHPerCoder
> I don't like the accusative tone when talking engineering.

That's fair.

I wrote this in 2017 to give a single page arguments against the JOSE
standards. The accusative tone is required by the fact that _the entire page
exists to attack the standard_ , based on technical arguments.

The target audience of the Paragon Initiative blog has always been "PHP
developers", and PHP gives you a built-in session mechanism. Which, if you're
writing PHP, you should _just use_. Session security in modern PHP boils down
to "use HTTPS".

If you're doing some massively distributed system (the likes of a FAANG
company project), you can disregard the advice aimed at LAMP stacks.

------
dangerface
Name a security standard written by some one other than DJB that doesn't
recommend bad defaults. It's almost as tho a three letter agency with more
money than sense is just paying people to write weak standards.

Just because the security idea can and is done poorly doesn't mean that the
idea is inherently insecure. We need to see security as an ongoing process not
a one time fire and forget thing.

Security like encryption always gets weaker it doesn't get stronger. It's a
bad idea to dismiss JWT or similar because the standard has gotten weaker as
our understanding gets better.

~~~
CiPHPerCoder
> Name a security standard written by some one other than DJB that doesn't
> recommend bad defaults.

Sure, here's one at random: [https://github.com/awslabs/aws-encryption-sdk-
specification](https://github.com/awslabs/aws-encryption-sdk-specification)

DJB is not one of the authors of that specification. ;)

~~~
skrebbel
Obviously you're too humble to plug your own efforts, but isn't "sensible
defaults" the whole point of PASETO as well?

------
wadkar
If you like video consumption, a DEFCON 2018 talk by the author Scott
Arciszewski on this same topic can be found here:

No Way JOSE! Designing Cryptography:

[https://www.youtube.com/watch?v=RijGNytjbOI](https://www.youtube.com/watch?v=RijGNytjbOI)

You're welcome :)

Edit: Clarify that Scott is the author of both post and video.

------
rvz
TLDR: Use PASETO [0] or its simpler alternative Branca [1].

JWT/JWS/JWE are classic examples of bad standards that the industry has chosen
to adopt because everyone else is using it. It is a downgrade in terms of
usability, cryptography and even in some cases performance. As for sessions,
just don't even think about using it with that.

Just use PASETO [0] or Branca [1] tokens which are clearly both actively
worked on secure alternatives to JWT which make it harder to shoot yourself in
the foot with usability.

[0] [https://paseto.io](https://paseto.io)

[1] [https://branca.io](https://branca.io)

------
bshacklett
> If you need some bizarre stateless property for horizontal scaling your
> sessions...

> It is overwhelmingly likely that you do not needed crazy horizontal scaling
> schemes at all, and that a single server-side session management system is
> sufficient for your use case...

This feels quite short-sighted to me, even in 2017. Architecture for
supporting highly available systems and so-called "crazy" horizontal scaling
are not so different from each other, and pretty much everyone can benefit
significantly from a highly available and fault tolerant architecture.

Stateless application architecture is significantly helpful in keeping a
system simple and easy to deploy, which has huge impacts on overall
development processes, ability to remediate vulnerabilities and ability to
respond to changing requirements.

~~~
andybak
> pretty much everyone can benefit significantly from a highly available and
> fault tolerant architecture.

Yes but these are very hard problems and you've only given one side of the
cost benefit equation.

~~~
bshacklett
What are the problems that haven't been solved? Stateless application servers
have been reasonably commonplace for years, now, which is the main hurdle that
I've needed to surmount. The majority of other issues can be handled at the
platform level.

It's a lot of work to refactor an application, and sometimes that doesn't make
sense, but a blanket dismissal of the usefulness of proper architecture
because an application isn't running at Google or Facebook's scale does little
to help push technology and practices forward.

------
sascha_sl
Oh yes, throw out OIDC and let's go back to SAML.

While I understand that complexity in standards might be bad because they
allow you to shoot yourself in the foot, I am definitely not going to stop
using JWKs with JWT/JWS, those formats are actually quite simple and have
allowed us to deploy authenticating proxies essentially everywhere instead of
network based access control (which was always kind of broken), with slow key
rotation included (thanks keycloak)

Libraries should require the user to use pinned algos. Period.

~~~
CiPHPerCoder
> Oh yes, throw out OIDC and let's go back to SAML.

Aside from tptacek's observation: What prohibits the development of an OpenID
Connect PASETO variant? (This is a rhetorical question.)

~~~
sascha_sl
Adoption? Standardization?

Not everything is a green field. Yes, I get to deal with SAML a lot, and with
how quirky and incomplete and outright non-standard compliant some
implementations, particularly for SaaS services are (and how there are always
guides for Auth0, Otka and maybe ADFS, but never in plan SAML 2.0 terms), but
we also use OIDC for a few more modern services, like Kubernetes and our own
proxy and the amount of troubleshooting required has been essentially zero.

~~~
CiPHPerCoder
> Adoption? Standardization?

Working on that.

One of the goals of the PASETO project is to eliminate the use of JWT in
modern standards, not to eliminate the standards that currently (but
hopefully, temporarily) use JWT.

------
jchanimal
I found Cisco’s wrappers for WebCrypto implementing JOSE to be good and I
don’t plan to avoid it. [https://github.com/cisco/node-
jose](https://github.com/cisco/node-jose)

~~~
detaro
What about those wrappers avoids the problems described in the article?

~~~
jchrisa
I’m pretty sure they make it hard to shoot yourselves in the foot. It’s been a
while.

~~~
bvrmn
No, by default library allow "none" alg. And there is no mandatory option to
limit algs. Your foot is no more.

var DEFAULT_OPTIONS = { algorithms: "*", allowEmbeddedKey: false };

------
thefounder
Sure JOSE is bad but the author gives no real alternatives to JOSE. A session
cookie has little in common with JOSE. The author ignores the need for SSO and
distributed authentication. The idp is free to use whatever algo it wants even
if it's not in the algo list from the linked RFCs. Whoever wants to
authenticate can surely implement the given algo(Most likely it just needs to
import it from a standard library.)

~~~
icebraining
> the author gives no real alternatives to JOSE.

He does that right below the title: "Update (March 2018): Paseto is a Secure
Alternative to the JOSE Standards (JWT, etc.)"

~~~
thefounder
I can't find the specification/rfc of Paseto. It looks more of a php lib. To
me it seems the author is not familiar with JWT[0] and tries to solve the
wrong problems(e.g assumes the idp or library being used are compromised.)

[0] >> This decodes to:

Version: v2 Purpose: local (shared-key authenticated encryption) Payload (hex-
encoded):

JWT has an 'aud' param that serves the same purpose as "Purpose" here and
more. Versioning makes it even worse and doesn't solve any security issue. If
v1 is compromised the client should not be allowed to use it.

~~~
fraktl
From your two comments, it's clear you skimmed the text you're trying to
discuss here. How can your opinion be regarded as relevant in any way? You
highlight that author is not familiar with something (he is, he's actually
well respected expert who explains everything in fine detail), yet you've
shown you don't read carefully at all.

I found PASETO's website, rfc and github within.. 3 seconds of using my PC.
I'm 100% sure you're capable of doing the same.

Your comment looks like unnecessary criticism because you feel provoked since
someone criticized a piece of technology you use.

~~~
thefounder
Let me ask you this: wouldn't make more sense to publish a rfc for a more
strict JOSE (i.e only secure alg; no "none" option etc) and at the same time
develop a secure by default JOSE library rather than to invent a new protocol,
with a new format and new libraries? I can surely write some bad libraries for
PASETO and someone could come up with the same arguments against PASETO like
the OP.

~~~
CiPHPerCoder
> I can surely write some bad libraries for PASETO and someone could come up
> with the same arguments against PASETO like the OP.

The specification is here:
[https://github.com/paragonie/paseto/tree/master/docs](https://github.com/paragonie/paseto/tree/master/docs)

If you can write an insecure implementation without violating the
specification, please file an issue on Github.

~~~
skrebbel
Here's another thing I like about PASETO: because it's versioned,
communicating about insecurities found further down the line is much easier.

With JWT you have to say stuff like "ensure that alg can't be 'none' and that
your JWT library doesn't accept arbitrary alg fields". This is messy.

With PASETO you can just say "be sure to use v3 or later" (assuming someone
finds a flaw in v2, files that issue, and that is then addressed in a v3 of
the spec). Similarly, implementations can just write "supports versions 1
through 3" on their README.

~~~
thefounder
Nothing stops you from versioning JOSE. You may start with version 1 right now
and consider anything beneath it insecure.

------
api
Dynamic languages with no compile time checking of fields, assertions, etc.
seem inherently very dangerous to me for anything security critical or
cryptographic.

Sure you can write secure and correct code in them, but what happens years
later when others (including yourself after you've forgotten what you wrote!)
have come and made various edits, changes, refactors, etc.

This is generally where dynamic languages crash and burn, but it's
particularly dangerous with stuff like authentication where a bug can be
disastrous.

~~~
onlydeadheroes
Indeed it is much better to implement it in a language such as C or C++ that
has historically had almost no security issues and has very few pitfalls.

~~~
detaro
Please don't attack arguments the parent comment didn't make.

~~~
onlydeadheroes
Of course, because security issues and language pitfalls have no bearing on
cryptographic implementations.

~~~
detaro
"Dynamic languages have issues" does not say "all other languages are good".

~~~
onlydeadheroes
He is saying dynamic languages crash and burn in this context. Specifying
"dynamic" does strongly suggest non-dynamic languages do not crash and burn in
this context.

