> **Update (March 2018)**: [Paseto is a Secure Alternative to the JOSE Standards (JWT, etc.)](https://paragonie.com/blog/2018/03/paseto-platform-agnostic-security-tokens-is-secure-alternative-jose-standards-jwt-etc) --- If you've already decided to implement Javascript Object Signing and Encryption (JOSE), whether you want JSON Web Tokens, JSON Web Encryption (JWE), or JSON Web Signatures (JWS), you should question this decision. You're probably making a mistake. Everything in this blog post was written to be accurate as of [RFC 7519](https://tools.ietf.org/html/rfc7519), [RFC 7515](https://tools.ietf.org/html/rfc7515), and [RFC 7516](https://tools.ietf.org/html/rfc7516). It's possible that new RFCs in the future could supersede the flaws detailed within. If you're not already familiar with basic cryptography terms and concepts, [start here](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded). Hyperlinks are provided throughout the article to explain things in detail, for the sake of brevity. # Why You Don't Want Javascript Object Signing and Encryption There are several problems with the JOSE family of standards. These are not flaws specific to any particular implementation, and in fact many libraries *work around* the deficits of the standards.

JSON Web Tokens are Often Misused

A lot of developers try to use JWT to avoid server-side storage for sessions. This is [almost always a terrible mistake](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) and invites developers to come up with [clever explanations and workarounds instead of careful engineering](http://cryto.net/%7Ejoepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/). The two linked posts explain succinctly why this is a bad move, so I won't delve further into the systems architecture issues. There are more pressing issues at stake: **The standard itself is bad and leads to insecurity.**

JSON Web Signatures Makes Forgery Trivial

JSON Web Signatures (JWS) is a standard that is supposed to provide [message authentication](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded#mac) or [digital signatures](https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded#digital-signatures). In general terms: When a cryptography protocol includes digital signatures or message authentication, if an attacker can successfully forge arbitrary messages at a low cost, we consider the protocol to be completely broken. Quoting [RFC 7515, section 4.1.1](https://tools.ietf.org/html/rfc7515#section-4.1.1): > The "alg" (algorithm) Header Parameter identifies the cryptographic > algorithm used to secure the JWS. The JWS Signature value is not > valid if the "alg" value does not represent a supported algorithm or > if there is not a key for use with that algorithm associated with the > party that digitally signed or MACed the content. "alg" values > should either be registered in the IANA "JSON Web Signature and > Encryption Algorithms" registry established by [JWA] or be a value > that contains a Collision-Resistant Name. The "alg" value is a case- > sensitive ASCII string containing a StringOrURI value. **This Header > Parameter MUST be present and MUST be *understood and processed* by > implementations.** We've seen this bite JWS users before, in the form of [critical vulnerabilities in most JWT libraries](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). There were two ways to attack a standards-compliant JWS library to achieve trivial token forgery: 1. Send a header that specifies the "none" algorithm be used 2. Send a header that specifies the "HS256" algorithm when the application normally signs messages with an RSA public key. This isn't just an implementation bug, this is the result of a failed standard that shouldn't be relied on for security. If you adhere to the standard, you **must** process and "understand" the header. You are explicitly forbidden, by the standard, to just disregard the header that an attacker provides. #### What does "understood and processed" mean? This phrase is repeated throughout the JSON and JOSE RFCs, but a formal definition is not provided. Today, many libraries interpret "validate the `alg` header against a whitelist" as satisfying the "processed" requirement. Historically, given the previous [token forgery vulnerability enabled by changing the `alg` header](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/), this does not appear to have always been the case. While it's tempting to applaud developers for exploiting an ambiguity in a security protocol to improve the security of their implementations, that doesn't fix the standard.

JSON Web Encryption is a Foot-Gun

Encryption leaves [a lot of room for potential implementation errors](https://paragonie.com/blog/2015/05/using-encryption-and-authentication-correctly), especially when [asymmetric (a.k.a. public-key) encryption](https://paragonie.com/blog/2016/12/everything-you-know-about-public-key-encryption-in-php-is-wrong) is involved. The encryption algorithms permitted by JWE are spelled out in [RFC 7518](https://tools.ietf.org/html/rfc7518#page-2), which comes in two sections: * Key encryption, which gives you options such as: * RSA with PKCS #1v1.5 padding * RSA with OAEP padding * ECDH * AES-GCM * Message encryption, which only allows you to choose between: * AES-CBC + HMAC * AES-GCM Let's look at some of the **key encryption** choices in detail. The message encryption part is OK (assuming you actually have a solid GCM implementation and adequate hardware support). If you're not familiar with cryptography, this is somewhat like pointing a gun with 5 out of 6 loaded chambers directly at your foot and expecting to not end up with a bullet wound. Almost all of these options have one or more security issues. ### RSA with PKCS #1v1.5 Padding RSA with PKCS #1v1.5 padding is vulnerable to a type of chosen-ciphertext attack, called a **padding oracle**. We discussed [RSA attacks in detail here](https://paragonie.com/blog/2016/12/everything-you-know-about-public-key-encryption-in-php-is-wrong). ### RSA with OAEP Padding RSA with OAEP padding is probably secure. OAEP has a [bogus security proof](https://eprint.iacr.org/2000/060.pdf) but is far safer than PKCS1v1.5. However, there are serious doubts to the long-term security of RSA itself. Most cryptographers recommend migrating away from RSA. ### ECDH JWT only allows Elliptic Curve Diffie-Hellman (ECDH) over one of the NIST curves (Weierstrass curves, which introduce the risk of [invalid-curve attacks](https://blogs.adobe.com/security/2017/03/critical-vulnerability-uncovered-in-json-encryption.html) that attackers to steal your secret keys). If you attempt to avoid invalid curve attacks by using [one of the elliptic curves for security](https://tools.ietf.org/html/rfc7748), you're no longer JWT standards-compliant. ### AES-GCM Because no list of questionable public-key encryption modes could be complete without shoehorning a shared-key encryption mode, the JOSE standards also allow you to use AES-GCM to possibly exchange an AES-GCM key. ----- Cryptography algorithm selections should be made by professional cryptographers, not developers. Letting developers mix-and-match protocols and algorithms is the hallmark of [error-prone cryptographic designs](http://bristolcrypto.blogspot.com/2015/01/real-world-crypto-2015-error-prone.html). > Aside: the [recent invalid curve attacks in JOSE](https://blogs.adobe.com/security/2017/03/critical-vulnerability-uncovered-in-json-encryption.html) mentioned in this section are definitely worth reading, if you haven't already done so.

A Better Solution than JOSE

A better standard would only let you choose two parameters: * **`ver`** - Which version of the protocol to use, which defines "one true ciphersuite" for each version; what follows are pure examples: * v1: Ed25519, X25519, XSalsa20poly1305, HMAC-SHA-512-256 * v2: Ed448, X448, XChaCha20Poly1305, keyed BLAKE2b * v3: [Something Post-Quantum](https://csrc.nist.gov/projects/post-quantum-cryptography/round-1-submissions) with [AEAD](https://competitions.cr.yp.to/caesar.html) * **`op`** - What operation to perform: * Authenticated encryption * Message authentication * Public-key authenticated encryption (for server-to-server communications only) * Public-key digital signatures (for server-to-server communications only) Public-key cryptography should be avoided if possible. The closest we have to a better standard today is [Fernet](https://github.com/fernet/spec). We're developing a simply secure alternative, called [PASETO (Platform-Agnostic Security Tokens)](https://github.com/paragonie/paseto). ## Wrap-Up So in conclusion: * Don't use JWT for session management, as discussed in other articles * The JWS standard is completely broken, and total RFC compliance renders your applications vulnerable * The JWE standard is a minefield that non-cryptographers shouldn't be forced to navigate * JOSE is a needlessly complex suite of standards with security deficits baked in

What to use instead of JOSE / JWT / JWE / JWS?

As stated above, [Fernet](https://github.com/fernet/spec) is an option for most JWT use-cases. In the near future, [PASETO](https://github.com/paragonie/paseto) will hopefully replace JOSE in the modern web. That being said: * For [secure sessions](https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions): Just use cookies over HTTPS. Cookies should only store a random identifier which is paired with a server-side persistent storage mechanism. * For signatures: Libsodium's `crypto_sign()` or `crypto_auth()` APIs ([depending on use-case](https://paragonie.com/blog/2017/06/libsodium-quick-reference-quick-comparison-similar-functions-and-which-one-use)). * For encryption: Libsodium's `crypto_secretbox()` and `crypto_box()` APIs (depending on use-case). * If you need some bizarre stateless property for horizontal scaling your sessions (and [are certain you're not making a mistake](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions)), see the previous recommendation about signatures. * 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. We've included this list item for the sake of completeness. * However, if by some bizarre twist of fate your project is in the <0.1% of systems, your organization is probably big enough to know how to solve this problem *without* JWT. We've previously published material about [secure token-based authentication](https://paragonie.com/blog/2017/02/split-tokens-token-based-authentication-protocols-without-side-channels) and [cross-domain user authentication](https://paragonie.com/blog/2016/02/one-login-rule-them-all-seamless-and-secure-cross-domain-authentication) which totally obviates the need for JSON Web Tokens. # TL;DR JOSE / JWT / JWS / JWE: Not even once.