Repository: cxf Updated Branches: refs/heads/3.0.x-fixes 807605c33 -> 105f1e777
Simplifying JWS JSON filter consumers to validate a single signature only same as JWE JSON decrypts a single entry only, the extra entries will be available for further processing as needed Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/105f1e77 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/105f1e77 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/105f1e77 Branch: refs/heads/3.0.x-fixes Commit: 105f1e777c1a48e8734d174d2caa05f3bcfb762b Parents: 807605c Author: Sergey Beryozkin <[email protected]> Authored: Wed Mar 2 16:26:12 2016 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Wed Mar 2 16:40:41 2016 +0000 ---------------------------------------------------------------------- .../jaxrs/AbstractJwsJsonReaderProvider.java | 74 ++++++-------------- .../jose/jaxrs/JwsJsonClientResponseFilter.java | 5 +- .../jaxrs/JwsJsonContainerRequestFilter.java | 9 +-- .../rs/security/jose/jws/JwsJsonConsumer.java | 63 +++++++++++------ .../security/jose/jws/JwsJsonConsumerTest.java | 18 ----- .../security/jose/jwejws/JAXRSJwsJsonTest.java | 12 +++- .../security/jose/jwejws/serverJwsJson.xml | 4 +- 7 files changed, 80 insertions(+), 105 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java index 5b328e4..8555006 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java @@ -18,18 +18,13 @@ */ package org.apache.cxf.rs.security.jose.jaxrs; -import java.util.Arrays; import java.util.Collections; -import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.logging.Logger; import org.apache.cxf.common.logging.LogUtils; -import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.message.Message; -import org.apache.cxf.message.MessageUtils; -import org.apache.cxf.rs.security.jose.common.JoseConstants; import org.apache.cxf.rs.security.jose.jws.JwsException; import org.apache.cxf.rs.security.jose.jws.JwsJsonConsumer; import org.apache.cxf.rs.security.jose.jws.JwsJsonSignatureEntry; @@ -39,49 +34,21 @@ import org.apache.cxf.rs.security.jose.jws.JwsUtils; public class AbstractJwsJsonReaderProvider { protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJwsJsonReaderProvider.class); - private List<JwsSignatureVerifier> sigVerifiers; + private JwsSignatureVerifier sigVerifier; private String defaultMediaType; - private boolean strictVerification; + private Map<String, Object> entryProps; public void setSignatureVerifier(JwsSignatureVerifier signatureVerifier) { - setSignatureVerifiers(Collections.singletonList(signatureVerifier)); - } - public void setSignatureVerifiers(List<JwsSignatureVerifier> signatureVerifiers) { - this.sigVerifiers = signatureVerifiers; + this.sigVerifier = signatureVerifier; } - @SuppressWarnings("deprecation") - protected List<JwsSignatureVerifier> getInitializedSigVerifiers() { - if (sigVerifiers != null) { - return sigVerifiers; - } - Message m = JAXRSUtils.getCurrentMessage(); - Object propLocsProp = - MessageUtils.getContextualProperty(m, JoseConstants.RSSEC_SIGNATURE_IN_PROPS, - JoseConstants.RSSEC_SIGNATURE_PROPS); - if (propLocsProp == null) { - propLocsProp = - MessageUtils.getContextualProperty(m, JoseConstants.DEP_RSSEC_SIGNATURE_IN_LIST_PROPS, - JoseConstants.DEP_RSSEC_SIGNATURE_LIST_PROPS); - } - if (propLocsProp == null) { - LOG.warning("JWS JSON init properties resource is not identified"); - throw new JwsException(JwsException.Error.NO_INIT_PROPERTIES); - } - List<String> propLocs = null; - if (propLocsProp instanceof String) { - String[] props = ((String)propLocsProp).split(","); - propLocs = Arrays.asList(props); - } else { - propLocs = CastUtils.cast((List<?>)propLocsProp); - } - List<JwsSignatureVerifier> theSigVerifiers = new LinkedList<JwsSignatureVerifier>(); - for (String propLoc : propLocs) { - theSigVerifiers.addAll(JwsUtils.loadSignatureVerifiers(propLoc, m)); - } - return theSigVerifiers; + protected JwsSignatureVerifier getInitializedSigVerifier() { + if (sigVerifier != null) { + return sigVerifier; + } + return JwsUtils.loadSignatureVerifier(null, true); } - + public String getDefaultMediaType() { return defaultMediaType; } @@ -89,21 +56,24 @@ public class AbstractJwsJsonReaderProvider { public void setDefaultMediaType(String defaultMediaType) { this.defaultMediaType = defaultMediaType; } - public boolean isStrictVerification() { - return strictVerification; - } - public void setStrictVerification(boolean strictVerification) { - this.strictVerification = strictVerification; - } - protected void validate(JwsJsonConsumer c, List<JwsSignatureVerifier> theSigVerifiers) throws JwsException { + + protected void validate(JwsJsonConsumer c, JwsSignatureVerifier theSigVerifier) throws JwsException { - List<JwsJsonSignatureEntry> remaining = c.verifyAndGetNonValidated(theSigVerifiers, - isStrictVerification()); + List<JwsJsonSignatureEntry> remaining = + c.verifyAndGetNonValidated(Collections.singletonList(theSigVerifier), entryProps); if (!remaining.isEmpty()) { JAXRSUtils.getCurrentMessage().put("jws.json.remaining.entries", remaining); } JAXRSUtils.getCurrentMessage().put(JwsJsonConsumer.class, c); } + + public Map<String, Object> getEntryProps() { + return entryProps; + } + + public void setEntryProps(Map<String, Object> entryProps) { + this.entryProps = entryProps; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java index dc9a352..e342577 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java @@ -20,7 +20,6 @@ package org.apache.cxf.rs.security.jose.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.List; import javax.annotation.Priority; import javax.ws.rs.client.ClientRequestContext; @@ -37,9 +36,9 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; public class JwsJsonClientResponseFilter extends AbstractJwsJsonReaderProvider implements ClientResponseFilter { @Override public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException { - List<JwsSignatureVerifier> theSigVerifiers = getInitializedSigVerifiers(); + JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); JwsJsonConsumer c = new JwsJsonConsumer(IOUtils.readStringFromStream(res.getEntityStream())); - validate(c, theSigVerifiers); + validate(c, theSigVerifier); byte[] bytes = c.getDecodedJwsPayloadBytes(); res.setEntityStream(new ByteArrayInputStream(bytes)); res.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java index 3b705a3..56cf430 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java @@ -20,7 +20,6 @@ package org.apache.cxf.rs.security.jose.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.List; import javax.annotation.Priority; import javax.ws.rs.HttpMethod; @@ -44,14 +43,10 @@ public class JwsJsonContainerRequestFilter extends AbstractJwsJsonReaderProvider if (HttpMethod.GET.equals(context.getMethod())) { return; } - List<JwsSignatureVerifier> theSigVerifiers = getInitializedSigVerifiers(); - if (theSigVerifiers.isEmpty()) { - context.abortWith(JAXRSUtils.toResponse(400)); - return; - } + JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); JwsJsonConsumer c = new JwsJsonConsumer(IOUtils.readStringFromStream(context.getEntityStream())); try { - validate(c, theSigVerifiers); + validate(c, theSigVerifier); } catch (JwsException ex) { context.abortWith(JAXRSUtils.toResponse(400)); return; http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java index e8d9a41..22e781f 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java @@ -123,10 +123,17 @@ public class JwsJsonConsumer { return JwsUtils.getJwsJsonSignatureMap(signatures); } public boolean verifySignatureWith(JwsSignatureVerifier validator) { + return verifySignatureWith(validator, null); + } + public boolean verifySignatureWith(JwsSignatureVerifier validator, Map<String, Object> entryProps) { List<JwsJsonSignatureEntry> theSignatureEntries = getSignatureEntryMap().get(validator.getAlgorithm()); if (theSignatureEntries != null) { for (JwsJsonSignatureEntry signatureEntry : theSignatureEntries) { + if (entryProps != null + && !signatureEntry.getUnionHeader().asMap().entrySet().containsAll(entryProps.entrySet())) { + continue; + } if (signatureEntry.verifySignatureWith(validator)) { return true; } @@ -135,40 +142,56 @@ public class JwsJsonConsumer { return false; } public boolean verifySignatureWith(PublicKey key, SignatureAlgorithm algo) { - return verifySignatureWith(JwsUtils.getPublicKeySignatureVerifier(key, algo)); + return verifySignatureWith(key, algo, null); + } + public boolean verifySignatureWith(PublicKey key, SignatureAlgorithm algo, Map<String, Object> entryProps) { + return verifySignatureWith(JwsUtils.getPublicKeySignatureVerifier(key, algo), entryProps); } public boolean verifySignatureWith(byte[] key, SignatureAlgorithm algo) { - return verifySignatureWith(JwsUtils.getHmacSignatureVerifier(key, algo)); + return verifySignatureWith(key, algo, null); + } + public boolean verifySignatureWith(byte[] key, SignatureAlgorithm algo, Map<String, Object> entryProps) { + return verifySignatureWith(JwsUtils.getHmacSignatureVerifier(key, algo), entryProps); + } + public boolean verifySignatureWith(JsonWebKey key) { + return verifySignatureWith(JwsUtils.getSignatureVerifier(key)); + } + public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo) { + return verifySignatureWith(key, algo, null); + } + public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo, Map<String, Object> entryProps) { + return verifySignatureWith(JwsUtils.getSignatureVerifier(key, algo), entryProps); } - public boolean verifySignatureWith(List<JwsSignatureVerifier> validators) { - return verifySignatureWith(validators, false); + return verifySignatureWith(validators, null); } - public boolean verifySignatureWith(List<JwsSignatureVerifier> validators, - boolean validateAll) { + public boolean verifySignatureWith(List<JwsSignatureVerifier> validators, Map<String, Object> entryProps) { try { - verifyAndGetNonValidated(validators, validateAll); + verifyAndGetNonValidated(validators, entryProps); } catch (JwsException ex) { LOG.warning("One of JSON JWS signatures is invalid"); return false; } return true; } - + public List<JwsJsonSignatureEntry> verifyAndGetNonValidated(List<JwsSignatureVerifier> validators) { - return verifyAndGetNonValidated(validators, false); + return verifyAndGetNonValidated(validators, null); } - - public List<JwsJsonSignatureEntry> verifyAndGetNonValidated(List<JwsSignatureVerifier> validators, - boolean validateAll) { + public List<JwsJsonSignatureEntry> verifyAndGetNonValidated(List<JwsSignatureVerifier> validators, + Map<String, Object> entryProps) { List<JwsJsonSignatureEntry> validatedSignatures = new LinkedList<JwsJsonSignatureEntry>(); for (JwsSignatureVerifier validator : validators) { List<JwsJsonSignatureEntry> theSignatureEntries = getSignatureEntryMap().get(validator.getAlgorithm()); if (theSignatureEntries != null) { for (JwsJsonSignatureEntry sigEntry : theSignatureEntries) { + if (entryProps != null + && !sigEntry.getUnionHeader().asMap().entrySet().containsAll(entryProps.entrySet())) { + continue; + } if (sigEntry.verifySignatureWith(validator)) { validatedSignatures.add(sigEntry); break; @@ -185,13 +208,14 @@ public class JwsJsonConsumer { nonValidatedSignatures.add(sigEntry); } } - if (validateAll && !nonValidatedSignatures.isEmpty()) { - throw new JwsException(JwsException.Error.INVALID_SIGNATURE); - } return nonValidatedSignatures; } public String verifyAndProduce(List<JwsSignatureVerifier> validators) { - List<JwsJsonSignatureEntry> nonValidated = verifyAndGetNonValidated(validators, false); + return verifyAndProduce(validators, null); + + } + public String verifyAndProduce(List<JwsSignatureVerifier> validators, Map<String, Object> entryProps) { + List<JwsJsonSignatureEntry> nonValidated = verifyAndGetNonValidated(validators, entryProps); if (!nonValidated.isEmpty()) { JwsJsonProducer producer = new JwsJsonProducer(getDecodedJwsPayload()); producer.getSignatureEntries().addAll(nonValidated); @@ -200,11 +224,6 @@ public class JwsJsonConsumer { return null; } } - public boolean verifySignatureWith(JsonWebKey key) { - return verifySignatureWith(JwsUtils.getSignatureVerifier(key)); - } - public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo) { - return verifySignatureWith(JwsUtils.getSignatureVerifier(key, algo)); - } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java index 964400d..8a2f9a0 100644 --- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java +++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java @@ -117,24 +117,6 @@ public class JwsJsonConsumerTest extends Assert { assertEquals(KID_OF_THE_SECOND_SIGNER, remainingEntries.get(0).getKeyId()); } - - @Test(expected = JwsException.class) - public void testFailVerifyAllWithSingleValidator() throws Exception { - 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(); - assertEquals(KID_OF_THE_FIRST_SIGNER, firstKid); - JsonWebKey rsaKey = jwks.getKey(firstKid); - assertNotNull(rsaKey); - JwsSignatureVerifier jws = JwsUtils.getSignatureVerifier(rsaKey); - assertTrue(consumer.verifySignatureWith(jws)); - consumer.verifyAndGetNonValidated(Collections.singletonList(jws), true); - fail(); - } public JsonWebKeys readKeySet(String fileName) throws Exception { InputStream is = JwsJsonConsumerTest.class.getResourceAsStream(fileName); return JwkUtils.readJwkSet(is); http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJwsJsonTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJwsJsonTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJwsJsonTest.java index ba177ea..bffc974 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJwsJsonTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJwsJsonTest.java @@ -120,7 +120,11 @@ public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { List<String> properties = new ArrayList<String>(); properties.add("org/apache/cxf/systest/jaxrs/security/secret.jwk.properties"); properties.add("org/apache/cxf/systest/jaxrs/security/secret.jwk.hmac.properties"); - BookStore bs = createBookStore(address, properties, null); + Map<String, Object> map = new HashMap<String, Object>(); + map.put(JoseConstants.RSSEC_SIGNATURE_OUT_PROPS, properties); + map.put(JoseConstants.RSSEC_SIGNATURE_IN_PROPS, + "org/apache/cxf/systest/jaxrs/security/secret.jwk.hmac.properties"); + BookStore bs = createBookStore(address, map, null); Book book = bs.echoBook(new Book("book", 123L)); assertEquals("book", book.getName()); assertEquals(123L, book.getId()); @@ -131,7 +135,11 @@ public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { String address = "https://localhost:" + PORT + "/jwsjsonhmac2"; List<String> properties = new ArrayList<String>(); properties.add("org/apache/cxf/systest/jaxrs/security/secret.jwk.hmac2.properties"); - BookStore bs = createBookStore(address, properties, null); + Map<String, Object> map = new HashMap<String, Object>(); + map.put(JoseConstants.RSSEC_SIGNATURE_OUT_PROPS, properties); + map.put(JoseConstants.RSSEC_SIGNATURE_IN_PROPS, + "org/apache/cxf/systest/jaxrs/security/secret.jwk.properties"); + BookStore bs = createBookStore(address, map, null); Book book = bs.echoBook2(new Book("book", 123L)); assertEquals("book", book.getName()); assertEquals(123L, book.getId()); http://git-wip-us.apache.org/repos/asf/cxf/blob/105f1e77/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/serverJwsJson.xml ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/serverJwsJson.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/serverJwsJson.xml index 1cf78c8..840dfbd 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/serverJwsJson.xml +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/serverJwsJson.xml @@ -82,7 +82,9 @@ under the License. <ref bean="jwsOutFilter"/> </jaxrs:providers> <jaxrs:properties> - <entry key="rs.security.signature.properties" + <entry key="rs.security.signature.in.properties" + value="org/apache/cxf/systest/jaxrs/security/secret.jwk.hmac.properties"/> + <entry key="rs.security.signature.out.properties" value="org/apache/cxf/systest/jaxrs/security/secret.jwk.properties,org/apache/cxf/systest/jaxrs/security/secret.jwk.hmac.properties"/> </jaxrs:properties> </jaxrs:server>
