Common JWT security vulnerabilities and how to avoid them

The JSON Web Token standard has received a number of security reviews at the IETF and OIDF and is deemed sufficiently secure by experts. But this doesn't make it foolproof. You, as a developer, can easily shoot yourself in the foot by making inappropriate use of JWT or a library that implements it, including this one.

1. Never ever let the JWT header alone drive verification

Received JWTs must always be duly verified. When you do that, never ever let the JWT or any of its header parameters drive the verification process alone. Always have a clear cut contract in place, tailored to your application, that stipulates the permitted JWT algorithm and other header or payload parameters.

Do not attempt to cryptographically process a JWT before this initial screening is successfully passed. If you receive a JWT with an unexpected algorithm, discard it, and stop right there.

Remember that JWTs can come in as HMAC protected, signed, encrypted, or even completely unsecured (alg = none). That a JWT parses and has the correct format does not mean that it can be trusted. The most blatant way to make your app vulnerable is to get the alg header, and then immediately proceed to verify the JWT's HMAC or signature, without first checking if that JWT alg is acceptable at all. What will happen to your app if it gets an unsecured JWT with alg = none?

So remember, always have a clear cut contract in place, and use it to screen each JWT before attempting to decrypt it, or check its signature or HMAC.

OpenID Connect clients for example establish the permitted ID token security algorithms at registration time. ID tokens that don't match the expected algorithm get discarded on the spot.

Example ID token contract:

{ 
  "id_token_signed_response_alg"    : "RS256",
  "id_token_encrypted_response_alg" : "RSA-OAEP",
  "id_token_encrypted_response_enc" : "A128GCM"
}

OpenID Connect further specifies where the RSA or EC keys to validate an ID token can come from: that is the IdP's published JWK set URL, and nowhere else. Which key to use, if multiple are published at the JWK set URL? This is communicated by the kid (key ID) header parameter of the JWT.

{
  "alg" : "RS256",
  "kid" : "sho0jea6"
}

If you're validating ID tokens, use a well-tested and established library, such as Pac4j. Yes, we do maintain a comprehensive OpenID Connect SDK, but we suggest you use the higher-level Pac4j, as it provides a more dev-friendly package.

If you're going to validate JWTs as OAuth 2.0 access tokens - check out the example here. It demonstrates usage of the Nimbus JOSE+JWT framework for processing JWTs that takes into account all of the above.

2. Know the algorithms

Know your algorithms, and what security properties you can expect from them in terms of integrity, authenticity, non-repudiation and confidentiality.

A common mistake is equating Hash-based Message Authentication Codes (HMAC) with digital signatures. No, they are not the same, even though they use a common format (JSON Web Signature). Remember that the JWS format is also used for unsecured (alg = none) JWTs.

This library will not allow you to confuse unsecured JWTs with HMAC or digital signature protected JWTs, because it uses separate Java types for them. But other libraries may not enforce this. We have found that OOP and type safety are generally good for security.

If you're wondering what particular JWS or JWE algorithm to use for your app, check out our algorithm selection guide.

3. Use an appropriate key size

Make sure you use an appropriate key size for your application.

This library has a number of checks in place prevent usage of HMAC keys shorter than 256 bits, AES keys shorter than 128 bits, or RSA keys shorter than 1024 bits (for legacy apps, 2048 is becoming the new norm now). But beware that other libs may not do that.

Finally, remember to take all necessary measures to keep your shared or private keys secure. The Nimbus JOSE+JWT has ready support for plugging in Hardware Security Modules (HSMs), pieces of hardware that perform signing or encryption in a external device while keeping the keys inaccessible from the OS and software (in case they get compromised).



comments powered by Disqus