...
Code Block | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
JwsHeaders headerEntries = new JwsHeaders(SignatureAlgorithm.HS256);
producer | ||||
Code Block | ||||
| ||||
// 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 | ||||
---|---|---|---|---|
| ||||
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
...