Nimbus JOSE + JWT 3.0, redesigned and with AES key wrap support

Thanks to Melisa Halsband, a contributor from CertiVox UK, the Nimbus library can now handle JSON Web Tokens (JWT) and other objects encrypted with a shared key using the AES or AES/GCM key wrap algorithm.

These are the JWA identifiers for the newly added algorithms:

  • For AES key wrap encryption: A128KW, A192KW and A256KW
  • For AES GCM key wrap encryption: A128CGMKW, A192CGMKW and A256CGMKW

Support of AES key wrap necessitated a number of braking changes to the JOSE header and object classes. That cleared the way for a number of other significant changes in the new 3.0 release, all of which we hope you'll find useful :)

Simplified immutable headers

The plain / JWS / JWE header classes are now simplified and completely immutable, which makes for safer development. A builder is available to help you construct headers where you need to specify additional parameters than the mandatory alg and enc:

JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).
                   keyID("123").
                   contentType("text/plain").
                   customParam("exp", new Date().getTime()).
                   build();

To facilitate AES key wrap the JWE header was given direct support for the iv and tag parameter. We also added support for the new x4t#S256 (X.509 certificate SHA-256 thumbprint) header parameter added in draft 27 of the JOSE specs.

AES key wrap encryption

AES key wrap is useful in situations when you want to encrypt a message using a shared secret key, e.g. to ensure confidentiality of ID tokens in OpenID Connect where the client application has been issued with a simple client secret at registration.

Note that the key length must match the one required by the algorithm:

  • 128 bit key for A128KW
  • 192 bit key for A192KW
  • 256 bit key for A256KW
// Create JWE object
JWEHeader header = new JWEHeader(JWEAlgorithm.A128KW, EncryptionMethod.A128CBC_HS256);
Payload payload = new Payload("Hello world!");      
JWEObject jweObject = new JWEObject(header, payload);

// Encrypt with secret key
JWEEncrypter encrypter = new AESEncrypter(secretKey);
jweObject.encrypt(encrypter);

// Output JWE string
jweObject.serialize();

// ...


// Parse JWE string on recipient side
jweObject = JWEObject.parse(jweString);

// Decrypt with same secret key
JWEDecrypter decrypter = new AESDecrypter(key128);
jweObject.decrypt(decrypter);

// Get the decrypted payload
assertEquals("Hello world!", jweObject.getPayload().toString());

Encryption with AES GCM key wrap is similar, you just need to specify A128GCMKW as the JWE algorithm instead.

Serialising single-valued JWT audience (aud) claims

A developer complained that some JWT libraries cannot handle JWT audience (aud) values that are JSON arrays, even in the simple case (array with a single audience). To enable interop with such software we decided to modify the JWTClaimsSet class, so that single-valued aud claims are now output as a string.

JWT claims set with a single aud:

{
 "iss": "https://c2id.com",
 "sub": "alice",
 "aud": "http://app.example.com"
}

JWT claims set with multiple aud values:

{
 "iss": "https://c2id.com",
 "sub": "alice",
 "aud": [ "http://app1.example.com", "http://app2.example.com" ] 
}

Java 7 is now the minimum requirement

With the new 3.0 release you will now need Java 7 to build and run the library. Java 6 is no longer officially supported as of February 2013, so we decided to drop support for it too, and start enjoying the language features Java 7 has to offer (and are already eyeing Java 8, but we'll have to be patient ;)

Matching IETF specifications

From the JOSE WG:

From the OAuth WG:

Download

The Maven Dependency for the new 3.0 release:

<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>3.0</version>
</dependency>

For other methods check out the downloads page.