Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejava
titleCXF JWS Compact HMac
JwtClaims claims = new JwtClaims();
claims.setIssuer("joe");
claims.setExpiryTime(1300819380L);
claims.setClaim("http://example.com/is_root", Boolean.TRUE);

JwsCompactProducer jwsProducer = new JwsJwtCompactProducer(claims);

// Sign
// Load HmacJwsSignatureProvider directly, see the next example for the alternative approach
String jwsSequence = jwsProducer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY, SignatureAlgorithm.HS256));

// Validate
JwsJwtCompactConsumer jwsConsumer = new JwsJwtCompactConsumer(jwsSequence);

// Load HmacJwsSignatureVerifier directly, see the next example for the alternative approach
jwsConsumer.verifySignatureWith(new HmacJwsSignatureVerifier(ENCODED_MAC_KEY, SignatureAlgorithm.HS256)));

// Get the data
JwtClaims protectedClaims = jws.getJwtClaims();

In the above example, the data (JwtToken) is submitted to an instance of JwsCompactProducer (JwsJwtCompactProducer) and signed with an HMac key.

Here is another example:

Code Block
languagejava
titleCXF JWS Compact HMac
JwsCompactProducer jwsProducer = new JwsCompactProducer("Hello World");

// Load private RSA key from the JWK Key set stored on the disk
InputStream is = JsonWebKeyTest.class.getResourceAsStream(fileName);
JsonWebKeys keySet = JwkUtils.readJwkSet(is);
JsonWebKey jwkPrivateRsaKey = keySet.getKey("Private RSA Key");

// Sign
String jwsSequence = jwsProducer.signWith(jwkPrivateRsaKey);

// Validate
JwsCompactConsumer jwsConsumer = new JwsCompactConsumer// Sign
// Algorithm properties are set in the headers. In this case JwsHeaders do not have to be directly created 
// (see the next example), JwsCompactProducer will initialize them if needed and set an alorithm by checking 
// JwsSignatureProvider. JwsHeaders need to be initialized directly if not only algorithm but other properties
// set too

JwsHeaders headers = new JwsHeaders(SignatureAlgorithm.HS256);

// This is the actual data content, JWT in this case, but can be an arbitrary JSON or non-JSON data
JwtClaims claims = new JwtClaims();
claims.setIssuer("joe");
claims.setExpiryTime(1300819380L);
claims.setClaim("http://example.com/is_root", Boolean.TRUE);

JwsCompactProducer jwsProducer = new JwsJwtCompactProducer(claims);

// Load HmacJwsSignatureProvider directly, see the next example for the alternative approach
String jwsSequence = jwsProducer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY, SignatureAlgorithm.HS256));

// validate
JwsJwtCompactConsumer jws = new JwsJwtCompactConsumer(jwsSequence);

// Load HmacJwsSignatureVerifierPublic directly,RSA seeKey thefrom nextJava exampleJKS forStore
PublicKey thepublicRsaKey alternative approach
assertTrue(jws.verifySignatureWith(new HmacJwsSignatureVerifier(ENCODED_MAC_KEY,
                                       SignatureAlgorithm.HS256)));
= CryptoUtils.loadPublicKey(keyStoreLocation, keyStorePassword, keyAlias, KeyStore.getDefaultType()); 

jws.verifySignatureWith(publicRsaKey);

// Get the data
JwtClaimsString protectedClaimshelloWorldString = jwsjwsConsumer.getJwtClaimsgetDecodedJwsPayload();

In the above example, the data (JwtToken) is submitted to an instance of JwsCompactProducer (JwsJwtCompactProducer) and signed with an HMac key.

Here is another example:

this latest example a plain text sequence is encoded with a private RSA key loaded from the JWK store and validated with a public RSA key loaded from the existing Java JKS store.

JwsUtils utility class has a lot of helper methods to get JWS sequences created and validated.

JWS JSON

While JWS Compact is optimized and represents a concatenation of up to 3 Base64URL values, JWS JSON is an open JSON container, see Appendix 6.

The most interesting feature of JWS JSON is that allows a content be signed for multiple recipients. For example,  the immediate consumer will validate a signature with one key, forward the payload to the next consumer which will also validate the content with another key, etc.  

JwsJsonProducer and JwsJsonConsumer support producing and consuming JWS JSON sequences.

 

Code Block
languagejava
titleCXF JWS JSON
JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
JwsHeaders headerEntries = new JwsHeaders(SignatureAlgorithm.HS256);
              
producer
Code Block
languagejava
titleCXF JWS Compact HMac
// Sign
// Algorithm properties are set in the headers
JwsHeaders headers = new JwsHeaders(SignatureAlgorithm.HS256);

JwsCompactProducer jwsProducer = new JwsJwtCompactProducer(token);

// Load HmacJwsSignatureProvider directly, see the next example for the alternative approach
String jwsSequence = jwsProducer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY_1, SignatureAlgorithm.HS256));,

// validate
JwsJwtCompactConsumer jws = new JwsJwtCompactConsumer(jwsSequence);

// Load HmacJwsSignatureVerifier directly, see the next example for the   alternative approach
assertTrue(jws.verifySignatureWithheaderEntries);
producer.signWith(new HmacJwsSignatureVerifierHmacJwsSignatureProvider(ENCODED_MAC_KEY_2, SignatureAlgorithm.HS256),
                  headerEntries);
assertEquals(DUAL_SIGNED_JWS_JSON_DOCUMENT, producer.getJwsJsonSignedDocument());

JwsJsonConsumer consumer = new JwsJsonConsumer(DUAL_SIGNED_DOCUMENT); 

// Validate both signatures, see below how to validate and produce
JsonWebKeys jwks =   SignatureAlgorithm.HS256)readKeySet("jwkSet.txt");
        
List<JwsJsonSignatureEntry> sigEntries = consumer.getSignatureEntries();
assertEquals(2, sigEntries.size());

// Get1st the datasignature
JwtTokenString tokenfirstKid = jws.getJwtToken(String)sigEntries.get(0).getKeyId();

In the above example, the data (JwtToken) is submitted to an instance of JwsCompactProducer (JwsJwtCompactProducer) and signed with an HMac key.

 

 

 

 

JWS JSON

While JWS Compact is optimized and represents a concatenation of up to 3 Base64URL values, JWS JSON is an open JSON container, see Appendix 6.

The most interesting feature of JWS JSON is that allows a content be signed for multiple recipients. For example,  the immediate consumer will validate a signature with one key, forward the payload to the next consumer which will also validate the content with another key, etc.  

JwsJsonProducer and JwsJsonConsumer support producing and consuming JWS JSON sequences.

 

Code Block
languagejava
titleCXF JWS JSON
JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
JwsHeaders headerEntries = new JwsHeaders(SignatureAlgorithm.HS256);
              
producer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY_1, SignatureAlgorithm.HS256),
                  headerEntries);
producer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY_2, SignatureAlgorithm.HS256),
                  headerEntries);
assertEquals(DUAL_SIGNED_JWS_JSON_DOCUMENT, producer.getJwsJsonSignedDocument());

JwsJsonConsumer consumer = new JwsJsonConsumer(DUAL_SIGNED_DOCUMENT); 
JsonWebKeys jwks = readKeySet("jwkPublicJsonConsumerSet.txt");
        
List<JwsJsonSignatureEntry> sigEntries = consumer.getSignatureEntries();
assertEquals(2, sigEntries.size());

// 1st signature
String firstKid = (String)sigEntries.get(0).getKeyId();
JsonWebKey firstKey = jwks.getKey(firstKid);
assertTrue(sigEntries.get(0).verifySignatureWith(firstKey));
// 2nd signature
String secondKid = (String)sigEntries.get(1).getKeyId();
JsonWebKey secondKey = jwks.getKey(secondKid);
assertTrue(sigEntries.get(1).verifySignatureWith(secondKey));
JsonWebKey firstKey = jwks.getKey(firstKid);
assertTrue(sigEntries.get(0).verifySignatureWith(firstKey));
// 2nd signature
String secondKid = (String)sigEntries.get(1).getKeyId();
JsonWebKey secondKey = jwks.getKey(secondKid);
assertTrue(sigEntries.get(1).verifySignatureWith(secondKey));

// or if you wish to validate (ex with the firstKey loaded above) and forward it to the next consumer, do:
JwsSignatureProvider provider = JwsUtils.getSignatureProvider(firstKey);
String nextJwsJson = consumer.validateAndProduce(Collections.singletonList(provider));
// use WebClient to post nextJwsJson to the next consumer, with nextJwsJson being nearly identical to the original
// double-signed JWS JSON signature, minus the signature which was already validated, in this case nextJwsJson will only have a single
// signature 

   

Does it make sense to use JWS JSON if you do not plan to do multiple signatures ? Indeed, if it is only a single signature then using JWS Compact is a good alternative, likely to be used most often.

However, even if you do a single signature, you may still want to try JWS JSON because is is easier to observe the individual JWS JSON structure parts when, example, checking the logs or TCP-tracing HTTP requests/responses. This is especially true when we start talking about a clear payload option, see below.   

JWS with Detached Content

...