There are some changes and enhancements coming in the JWT policies in Apigee Edge.
The Highlights:
- New algorithms: ECDSA and PSS
- JWS is now supported
- Critical Headers
- VerifyJWT and VerifyJWS now support a JWKS uri
- For Generate*, key encryption algorithms beyond DES-EDE3-CBC
- dynamic top level claims
And here are some details:
- New algorithms: ECDSA and PSS
The Elliptic Curve algorithms and the RSASSA-PSS algorithms defined in the JWA spec are now supported in the GenerateJWT and VerifyJWT policies. The ECDSA algorithms use a type of public/private keypair that is similar to RSA keys, but not the same. These keys are known as elliptic curve keys. While an RSA key of various bit strength can be used with RS256, RS384, and RS512, the EC key is specific to the algorithm strength. So you need to use a distinct key for each of ES256 ES384 and ES512. Consult the openssl documentation for details on how to construct keypairs for ECDSA.
The RSASSA-PSS algorithm is very similar to the RSASSA-PKCS1_5 algorithm, the only difference is in the padding that is applied to the plaintext. You can use the same RSA keys with PS256, PS384, and PS512 that you have used with RS256, RS384, and RS512. I won’t make specific recommendations on whether you should use RS* or PS*, but I will point out that the UK OpenBanking is insisting on PS* over RS* for better security. - JWS is now supported
While the idea of signed JWT is very well understood, a signed JWT is really just a special case of a JWS. JWS describes how to sign “anything”. A JWT signs a JSON payload, but a JWS can have a payload of any type, including a stream of bytes that does not represent a JSON or a string at all. This is handy when you have image data or other binary data that you’d like to sign.
Apigee Edge now includes new policies with names GenerateJWS, VerifyJWS and DecodeJWS which are analogs to the JWT policies. The JWS policies support all the same key types and algorithms as JWT, including the newly supported ECDSA and PSS algorithms. The policies support detached content or embedded content. See the JWS spec for more details. - Critical Headers
In the JWS header (don’t be misled, the JWS header applies to the general case JWS as well as to the specific case of JWT), there are a number of properties with “well known” meanings. Such properties include typ, alg, and kid, referring to the type of the payload (which can take values like “JWT” or “JOSE”) the algorithm used (“RS256”, “ES384”, etc), and the identifier of the key used to sign the payload and header.
The “crit” header is also now supported by the Apigee Edge policies. The crit header specifies headers that MUST be understood by the receiving party. You can generate JWT (or JWS) containing headers with the crit property, and you can verify JWT that have headers with the crit property. Check the documentation for how this all works. - VerifyJWT and VerifyJWS now support a JWKS uri
You can now specify the uri of a public endpoint that returns a JWKS payload, in the verify* policies. This will tell the policy to retrieve the JWKS from the endpoint, and then verify the inbound JWT or JWS based on the public keys specified in the JWKS. This is really handy. Previously, you had to retrieve the JWKS “manually” with a preceding ServiceCallout policy. This is now automatic inside the Verify* policies. - For Generate*, key encryption algorithms beyond DES-EDE3-CBC
It is possible to specify encrypted private keys (either RSA or ECDSA types) to the Generate policies. Previously the only encryption algorithm supported was DES-EDE3-CBC. Now you can encrypt your private keys with a myriad of algorithms supported by openssl, including: -aes-128-cbc aes-128-cfb aes-128-ofb aes-192-cbc aes-192-cfb aes-192-ofb aes-256-cbc aes-256-cfb aes-256-ofb aes128 aes192 aes256 bf bf-cbc bf-cfb bf-ofb blowfish des des-cbc des-cfb des-ede-cbc des-ede-cfb des-ede-ofb des-ede3-cbc des-ede3-cfb des-ede3-ofb des-ofb des3 rc2 rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ofb . Note, not all crypto algorithms supported by openssl for encrypting private keys are supported by the generate* policies. Among those not supported: -aes-128-cfb1 aes-128-cfb8 aes-128-ctr aes-128-ecb aes-128-gcm aes-128-xts aes-192-cfb1 aes-192-cfb8 aes-192-ctr aes-192-ecb aes-192-gcm aes-256-cfb1 aes-256-cfb8 aes-256-ctr aes-256-ecb aes-256-gcm aes-256-xts bf-ecb camellia-128-cbc camellia-128-cfb camellia-128-cfb1 camellia-128-cfb8 camellia-128-ecb camellia-128-ofb camellia-192-cbc camellia-192-cfb camellia-192-cfb1 camellia-192-cfb8 camellia-192-ecb camellia-192-ofb camellia-256-cbc camellia-256-cfb camellia-256-cfb1 camellia-256-cfb8 camellia-256-ecb camellia-256-ofb camellia128 camellia192 camellia256 cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb chacha des-cfb1 des-cfb8 des-ecb des-ede des-ede3 des-ede3-cfb1 des-ede3-cfb8 desx desx-cbc gost89 gost89-cnt gost89-ecb id-aes128-GCM id-aes192-GCM id-aes256-GCM rc2-ecb rc4 rc4-40 rc4-hmac-md5 - dynamic top level claims
You can add an element like into either the Generate* or the Verify* policies in order to specify a dynamic set of claims to generate or verify. Previously the names of the claims needed to be known and specified at policy configuration time, while the values could be dynamic; now, both the names and the values can be dynamic. This also applies to claims for the signed header.
There is one case in which we have tightened the security around JWT (and JWS) - involving HS* algorithms. Previously the policies allowed weak keys when signing. Now, the keys must have the minimum size - 32 bytes for HS256, 48 for HS384 and 64 for HS512. With the upgrade, you will now get an error at runtime if you try to sign or verify with HS* using a key of insufficient length. To avoid this, use a stronger key.
Not included in this update is any support for JWE. Encrypted JSON Web Tokens are not yet natively supported by Apigee Edge builtin policies.
Check the release notes when they become available for full details.