A Java Callout for generating and validating JWTs is now available. The callout can be used to sign JWTs with HMAC or RSA algorithms. It can also be used to sign and then encrypt JWTs using AES and RSA based key management algorithms. In short, JSON Web Signing and JSON Web Encryption is supported. The implementation uses jose4j JWT library for signing and encryption algorithms.
Sample Java callout policy to generate a signed and then encrypted JWT is given below. Here the claims-json is updated with iss, aud and expiry (in minutes) properties. It is then signed with HMAC_SHA512 algorithm. Finally, it is encrypted using AES_256_CBC_HMAC_SHA_512 algorithm. For the final step, encryption/signing key is determined using a public key with RSA_OAEP key management algorithm.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout async="false" continueOnError="false" enabled="true" name="JC-JWTGenerate">
<DisplayName>JC-JWTGenerate</DisplayName>
<FaultRules/>
<Properties>
<Property name="jws">true</Property>
<Property name="jws-algo">HMAC_SHA512</Property>
<Property name="jws-key">lr7LQmTSqre2v ... q7L1M/ZKJWhBLw==</Property>
<Property name="jwe">true</Property>
<Property name="jwe-algo">AES_256_CBC_HMAC_SHA_512</Property>
<Property name="jwe-key-algo">RSA_OAEP</Property>
<Property name="jwe-key">-----BEGIN PUBLIC KEY-----
MIIBIjAN ... PwIDAQAB
-----END PUBLIC KEY-----</Property>
<Property name="claims-json">{"sub":"John Doe","email":"johndoe@gmail.com"}</Property>
<Property name="iss">issuer-name</Property>
<Property name="aud">audience-1</Property>
<Property name="expiry">300</Property>
</Properties>
<ClassName>com.apigeecs.jwt.JWTGenerator</ClassName>
<ResourceURL>java://edge-jwt-generate.jar</ResourceURL>
</JavaCallout>
The JWTs generated above or by any OpenID Connect provider with same signing and encryption algorithm and private key, can be validated using the below Java Callout policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout async="false" continueOnError="false" enabled="true" name="JC-JWTGenerate">
<DisplayName>JC-JWTGenerate</DisplayName>
<FaultRules/>
<Properties>
<Property name="jws">true</Property>
<Property name="jws-algo">HMAC_SHA512</Property>
<Property name="jws-key">lr7LQmTSqre2v ... q7L1M/ZKJWhBLw==</Property>
<Property name="jwe">true</Property>
<Property name="jwe-algo">AES_256_CBC_HMAC_SHA_512</Property>
<Property name="jwe-key-algo">RSA_OAEP</Property>
<Property name="jwe-key">-----BEGIN PUBLIC KEY-----
MIIBIj ... PwIDAQAB
-----END PUBLIC KEY-----</Property>
<Property name="jwt">eyJhbGc ... eXk57TblVQ</Property>
<Property name="iss">issuer-name</Property>
<Property name="aud">audience-1</Property>
</Properties>
<ClassName>com.apigeecs.jwt.JWTValidator</ClassName>
<ResourceURL>java://edge-jwt-validate.jar</ResourceURL>
</JavaCallout>
Flow variables can also be used to specify property values. For details see https://github.com/gahana/edge-jwt-sample
This callout only deals with JWT generation and validation tasks and is not a full OpenID Connect implementation. For a general treatment of OpenID Connect implementation on Edge, look at https://github.com/apigee/iloveapis2015-jwt-jwe-jws. So what is the need for a separate JWT implementation? The OpenID Connect implementation done very early in JWT spec/library days used nimbus library for some of the flows and this needed security exceptions on Edge to run the Java Callout. The above implementation aims to provide a Java callout without the need for any security exceptions on Edge. It achieves this by using minimal dependencies while providing both signing and encryption capabilities.