The Encrypted JWT standard is very useful when producing APIs that support secure interactions.
Surely everyone by now is aware that TLS ought to be required between API clients and API endpoints (like those exposed by Apigee). And that a TLS -protected connection encrypts data on the network transport layer. Encryption means... an eavesdropper cannot read or interpret the data.
But the encryption stops at the TLS termination - in the case of an API client connecting to Apigee, encryption stops at Apigee's front door. The Apigee proxy can read all of the data that a client sends. This is obviously helpful, in most cases.
There may be some cases though, in which you'd like to apply application-layer (or message-layer) encryption, on top of TLS. One example might be a transaction that a client sends to Apigee, Apigee then verifies, and then Apigee sends the original transaction (perhaps enveloped) into an upstream system. That upstream system may store the original transaction. If the data format is a "signed JWT" then anyone with access to that storage system will be able to read the transaction - it's not private. But with an encrypted JWT, the transaction is private. It is readable only by a party that possesses the private key.
Another example might be a case in which the client sends an encrypted JWT to Apigee, and Apigee sends a signed version of that data to the upstream system .
There are many other possibilities.
What's new is, the existing JWT policies (GenerateJWT , VerifyJWT, and DecodeJWT) can now handle encrypted forms of JWT.
Here's a quick screencast introducing the capability.
Documentation for this new feature is forthcoming. In the meantime, a few usage notes.
The Supported Key encryption Algorithms are:
The supported Content Encryption Algorithms are:
When generating any encrypted JWT, you get to specify the Algorithms for key encryption and content encryption. These look like this:
<Algorithms> <Key>PBES2-HS512+A256KW</Key> <Content>A128GCM</Content> </Algorithms>
Select string values for those algorithms from the above.
Depending on the algorithm and operation, you will have to specify a particular kind of key. For example if you use the GenerateJWT and the RSA-OAEP-256 key encryption algorithm (kek), then you need to specify an RSA Public Key. If you use VerifyJWT and the ECDH-ES+A128KW kek, then you'd need to specify a ECDSA Private key.
For the A* algorithms, these all use AES and a symmetric key, that you can specify in configuration like this:
<SecretKey encoding='base64|base64url|base16|hex'> <Value ref='private.secretkey'/> </SecretKey>
For the PBES2-* algorithms, there is new support for generating a password-derived key via PBKDF2. You get to specify the salt length and the number of PBKDF2 iterations. For example, this is the configuration for a GenerateJWT that uses a PBES2-HS512+A256KW key-encryption.
<GenerateJWT name='enc-03'> <Algorithms> <Key>PBES2-HS512+A256KW</Key> <Content>A128GCM</Content> </Algorithms> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <PasswordKey> <Value ref='private.password'/> <SaltLength>16</SaltLength> <!-- in bytes --> <PBKDF2Iterations>50000</PBKDF2Iterations> </PasswordKey> <Subject>subject-here</Subject> <Issuer>issuer-here</Issuer> <Audience>audience-here</Audience> <OutputVariable>output_variable</OutputVariable> </GenerateJWT>
This should be available to use in your SaaS organization today. Hit me up here with questions on this.
One common Q, "How does this built-in feature compare to the Java callout available here?"
Answer: Functionally, the Java callout handles just RSA-OAEP or RSA-OAEP-256. It does not support the other Key encryption algorithms listed here. Also, this builtin policy is fully supported by Apigee.