[CXF-6915] Support for inlined unencoded payloads in JWS Compact
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/49658f95 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/49658f95 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/49658f95 Branch: refs/heads/master-jaxrs-2.1 Commit: 49658f950be04296afb7e5a8a49e572aeeff80c4 Parents: 517ef67 Author: Sergey Beryozkin <sberyoz...@gmail.com> Authored: Tue May 24 16:24:15 2016 +0100 Committer: Sergey Beryozkin <sberyoz...@gmail.com> Committed: Tue May 24 16:24:15 2016 +0100 ---------------------------------------------------------------------- .../jose/jaxrs/JwsWriterInterceptor.java | 22 ++++++++++++++---- .../security/jose/jws/JwsCompactConsumer.java | 6 ----- .../security/jose/jws/JwsCompactProducer.java | 3 --- .../security/jose/jwejws/JAXRSJweJwsTest.java | 13 +++++++++++ .../security/jose/jwejws/JAXRSJwsJsonTest.java | 24 +++++++++++++++++++- 5 files changed, 54 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/49658f95/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java index e4d8aff..6bf79ed 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java @@ -47,6 +47,7 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements WriterInterceptor { private boolean contentTypeRequired = true; private boolean useJwsOutputStream; + private boolean encodePayload = true; private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter(); @Override public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { @@ -57,6 +58,9 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W JwsHeaders headers = new JwsHeaders(); JwsSignatureProvider sigProvider = getInitializedSigProvider(headers); setContentTypeIfNeeded(headers, ctx); + if (!encodePayload) { + headers.setPayloadEncodingStatus(false); + } OutputStream actualOs = ctx.getOutputStream(); if (useJwsOutputStream) { JwsSignature jwsSignature = sigProvider.createJwsSignature(headers); @@ -65,12 +69,19 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W byte[] headerBytes = StringUtils.toBytesUTF8(writer.toJson(headers)); Base64UrlUtility.encodeAndStream(headerBytes, 0, headerBytes.length, jwsStream); jwsStream.write(new byte[]{'.'}); - - Base64UrlOutputStream base64Stream = new Base64UrlOutputStream(jwsStream); - ctx.setOutputStream(base64Stream); + + Base64UrlOutputStream base64Stream = null; + if (encodePayload) { + base64Stream = new Base64UrlOutputStream(jwsStream); + ctx.setOutputStream(base64Stream); + } else { + ctx.setOutputStream(jwsStream); + } ctx.proceed(); setJoseMediaType(ctx); - base64Stream.flush(); + if (base64Stream != null) { + base64Stream.flush(); + } jwsStream.flush(); } else { CachedOutputStream cos = new CachedOutputStream(); @@ -107,4 +118,7 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W MediaType joseMediaType = JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE); ctx.setMediaType(joseMediaType); } + public void setEncodePayload(boolean encodePayload) { + this.encodePayload = encodePayload; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/49658f95/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java index 9d57222..8ec1194 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java @@ -39,7 +39,6 @@ public class JwsCompactConsumer { private String jwsPayload; private String decodedJwsPayload; private JwsHeaders jwsHeaders; - private boolean detached; public JwsCompactConsumer(String encodedJws) { this(encodedJws, null, null); } @@ -67,7 +66,6 @@ public class JwsCompactConsumer { LOG.warning("Compact JWS includes a payload expected to be detached"); throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS); } - detached = true; jwsPayload = detachedPayload; } encodedSequence = parts[0] + "." + jwsPayload; @@ -106,10 +104,6 @@ public class JwsCompactConsumer { throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS); } jwsHeaders = new JwsHeaders(joseHeaders.asMap()); - if (JwsUtils.isPayloadUnencoded(jwsHeaders) && !detached) { - LOG.warning("Only detached payload can be unencoded"); - throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS); - } } return jwsHeaders; } http://git-wip-us.apache.org/repos/asf/cxf/blob/49658f95/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java index 53c1b0f..5523938 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java @@ -74,9 +74,6 @@ public class JwsCompactProducer { private String getSigningInput() { checkAlgorithm(); boolean unencoded = JwsUtils.isPayloadUnencoded(getJwsHeaders()); - if (unencoded && !detached) { - throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS); - } return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) + "." + (unencoded ? plainJwsPayload : Base64UrlUtility.encode(plainJwsPayload)); http://git-wip-us.apache.org/repos/asf/cxf/blob/49658f95/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java index 0d9e0d1..063b77d 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java @@ -254,6 +254,13 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { assertEquals("book", text); } @Test + public void testJwsJwkPlainTextHMacUnencoded() throws Exception { + String address = "https://localhost:" + PORT + "/jwsjwkhmac"; + BookStore bs = createJwsBookStore(address, null, false); + String text = bs.echoText("book"); + assertEquals("book", text); + } + @Test public void testJwsJwkBookHMac() throws Exception { String address = "https://localhost:" + PORT + "/jwsjwkhmac"; BookStore bs = createJwsBookStore(address, @@ -264,6 +271,11 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { } private BookStore createJwsBookStore(String address, List<?> mbProviders) throws Exception { + return createJwsBookStore(address, mbProviders, true); + } + private BookStore createJwsBookStore(String address, + List<?> mbProviders, + boolean encodePayload) throws Exception { JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); SpringBusFactory bf = new SpringBusFactory(); URL busFile = JAXRSJweJwsTest.class.getResource("client.xml"); @@ -273,6 +285,7 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { bean.setAddress(address); List<Object> providers = new LinkedList<Object>(); JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); + jwsWriter.setEncodePayload(encodePayload); jwsWriter.setUseJwsOutputStream(true); providers.add(jwsWriter); providers.add(new JwsClientResponseFilter()); http://git-wip-us.apache.org/repos/asf/cxf/blob/49658f95/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 0089bb7..9ee411b 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 @@ -79,6 +79,17 @@ public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { assertEquals("book", text); } @Test + public void testJwsJsonPlainTextHmacUnencoded() throws Exception { + String address = "https://localhost:" + PORT + "/jwsjsonhmac"; + BookStore bs = createBookStore(address, + Collections.singletonMap(JoseConstants.RSSEC_SIGNATURE_PROPS, + "org/apache/cxf/systest/jaxrs/security/secret.jwk.properties"), + null, + false); + String text = bs.echoText("book"); + assertEquals("book", text); + } + @Test public void testJwsJsonBookBeanHmac() throws Exception { String address = "https://localhost:" + PORT + "/jwsjsonhmac"; BookStore bs = createBookStore(address, @@ -170,11 +181,21 @@ public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { List<?> extraProviders) throws Exception { return createBookStore(address, Collections.singletonMap(JoseConstants.RSSEC_SIGNATURE_PROPS, properties), - extraProviders); + extraProviders, + true); } private BookStore createBookStore(String address, Map<String, Object> mapProperties, List<?> extraProviders) throws Exception { + return createBookStore(address, + mapProperties, + extraProviders, + true); + } + private BookStore createBookStore(String address, + Map<String, Object> mapProperties, + List<?> extraProviders, + boolean encodePayload) throws Exception { JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); SpringBusFactory bf = new SpringBusFactory(); URL busFile = JAXRSJwsJsonTest.class.getResource("client.xml"); @@ -185,6 +206,7 @@ public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { List<Object> providers = new LinkedList<Object>(); JwsJsonWriterInterceptor writer = new JwsJsonWriterInterceptor(); writer.setUseJwsJsonOutputStream(true); + writer.setEncodePayload(encodePayload); providers.add(writer); providers.add(new JwsJsonClientResponseFilter()); if (extraProviders != null) {