Repository: cxf Updated Branches: refs/heads/3.0.x-fixes 4110c8eae -> e027dc7d5
[CXF-6053] Adding JAXRS JwsJson filters and starting with the system testing Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/e027dc7d Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/e027dc7d Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/e027dc7d Branch: refs/heads/3.0.x-fixes Commit: e027dc7d5235f93d848861e07226ff9a1a1d1d23 Parents: 4110c8e Author: Sergey Beryozkin <[email protected]> Authored: Wed Oct 22 16:04:01 2014 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Wed Oct 22 16:05:25 2014 +0100 ---------------------------------------------------------------------- .../cxf/rs/security/jose/JoseConstants.java | 1 + .../jose/jaxrs/AbstractJweDecryptingFilter.java | 65 +----------- .../jaxrs/AbstractJwsJsonReaderProvider.java | 77 ++++++++++++++ .../jaxrs/AbstractJwsJsonWriterProvider.java | 79 ++++++++++++++ .../jose/jaxrs/AbstractJwsReaderProvider.java | 34 +----- .../jose/jaxrs/AbstractJwsWriterProvider.java | 38 +------ .../jose/jaxrs/JweWriterInterceptor.java | 77 +------------- .../jose/jaxrs/JwsJsonClientResponseFilter.java | 57 ++++++++++ .../jaxrs/JwsJsonContainerRequestFilter.java | 60 +++++++++++ .../jose/jaxrs/JwsJsonWriterInterceptor.java | 80 ++++++++++++++ .../jose/jaxrs/JwsWriterInterceptor.java | 4 +- .../cxf/rs/security/jose/jwa/Algorithm.java | 26 +++-- .../cxf/rs/security/jose/jwe/JweUtils.java | 105 +++++++++++++++++++ .../rs/security/jose/jws/JwsJsonConsumer.java | 63 +++++++++-- .../rs/security/jose/jws/JwsJsonProducer.java | 11 ++ .../jose/jws/JwsJsonSignatureEntry.java | 3 + .../cxf/rs/security/jose/jws/JwsUtils.java | 68 +++++++++++- .../security/jose/jws/JwsJsonConsumerTest.java | 4 +- .../jaxrs/security/jwt/BookServerJwsJson.java | 57 ++++++++++ .../jaxrs/security/jwt/JAXRSJwsJsonTest.java | 66 ++++++++++++ .../jaxrs/security/jwt/serverJwsJson.xml | 62 +++++++++++ 21 files changed, 811 insertions(+), 226 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java index a0b6a5b..6d95234 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java @@ -41,6 +41,7 @@ public final class JoseConstants { public static final String TYPE_JWT = "JWT"; public static final String TYPE_JOSE = "JOSE"; public static final String TYPE_JOSE_JSON = "JOSE+JSON"; + public static final String MEDIA_TYPE_JOSE = "application/jose"; public static final String MEDIA_TYPE_JOSE_JSON = "application/jose+json"; public static final String PLAIN_TEXT_ALGO = "none"; http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java index a1bd5cf..83e00e1 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java @@ -20,36 +20,19 @@ package org.apache.cxf.rs.security.jose.jaxrs; import java.io.IOException; import java.io.InputStream; -import java.security.interfaces.RSAPrivateKey; -import java.util.Properties; -import javax.crypto.SecretKey; - -import org.apache.cxf.Bus; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; -import org.apache.cxf.rs.security.jose.jwa.Algorithm; -import org.apache.cxf.rs.security.jose.jwe.AesCbcHmacJweDecryption; -import org.apache.cxf.rs.security.jose.jwe.AesGcmContentDecryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweDecryption; import org.apache.cxf.rs.security.jose.jwe.JweDecryptionOutput; import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider; import org.apache.cxf.rs.security.jose.jwe.JweHeaders; import org.apache.cxf.rs.security.jose.jwe.JweUtils; -import org.apache.cxf.rs.security.jose.jwe.KeyDecryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.RSAOaepKeyDecryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.WrappedKeyJweDecryption; -import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; -import org.apache.cxf.rs.security.jose.jwk.JwkUtils; public class AbstractJweDecryptingFilter { private static final String RSSEC_ENCRYPTION_IN_PROPS = "rs.security.encryption.in.properties"; private static final String RSSEC_ENCRYPTION_PROPS = "rs.security.encryption.properties"; - private static final String JSON_WEB_ENCRYPTION_KEY_ALGO_PROP = "rs.security.jwe.key.encryption.algorithm"; - private static final String JSON_WEB_ENCRYPTION_CEK_ALGO_PROP = "rs.security.jwe.content.encryption.algorithm"; private JweDecryptionProvider decryption; private String defaultMediaType; protected JweDecryptionOutput decrypt(InputStream is) throws IOException { @@ -75,53 +58,7 @@ public class AbstractJweDecryptingFilter { if (propLoc == null) { throw new SecurityException(); } - Bus bus = m.getExchange().getBus(); - try { - KeyDecryptionAlgorithm keyDecryptionProvider = null; - Properties props = ResourceUtils.loadProperties(propLoc, bus); - String contentEncryptionAlgo = props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP); - SecretKey ctDecryptionKey = null; - if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_ENCRYPT); - String keyEncryptionAlgo = getKeyEncryptionAlgo(props, jwk.getAlgorithm()); - if ("direct".equals(keyEncryptionAlgo)) { - contentEncryptionAlgo = getContentEncryptionAlgo(props, contentEncryptionAlgo); - ctDecryptionKey = JweUtils.getContentDecryptionSecretKey(jwk, contentEncryptionAlgo); - } else { - keyDecryptionProvider = JweUtils.getKeyDecryptionAlgorithm(jwk, keyEncryptionAlgo); - } - } else { - keyDecryptionProvider = new RSAOaepKeyDecryptionAlgorithm( - (RSAPrivateKey)KeyManagementUtils.loadPrivateKey( - m, props, KeyManagementUtils.RSSEC_DECRYPT_KEY_PSWD_PROVIDER)); - } - if (keyDecryptionProvider == null && ctDecryptionKey == null) { - throw new SecurityException(); - } - if (keyDecryptionProvider != null) { - if (Algorithm.isAesCbcHmac(contentEncryptionAlgo)) { - return new AesCbcHmacJweDecryption(keyDecryptionProvider, contentEncryptionAlgo); - } else { - return new WrappedKeyJweDecryption(keyDecryptionProvider, - new AesGcmContentDecryptionAlgorithm(contentEncryptionAlgo)); - } - } else { - return new DirectKeyJweDecryption(ctDecryptionKey, - new AesGcmContentDecryptionAlgorithm(contentEncryptionAlgo)); - } - } catch (SecurityException ex) { - throw ex; - } catch (Exception ex) { - throw new SecurityException(ex); - } - - } - - private String getKeyEncryptionAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_KEY_ALGO_PROP) : algo; - } - private String getContentEncryptionAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP) : algo; + return JweUtils.loadDecryptionProvider(propLoc, m); } public String getDefaultMediaType() { return defaultMediaType; http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java new file mode 100644 index 0000000..bf2bf2f --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonReaderProvider.java @@ -0,0 +1,77 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jaxrs; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +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.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.jose.jws.JwsUtils; + +public class AbstractJwsJsonReaderProvider { + private static final String RSSEC_SIGNATURE_IN_LIST_PROPS = "rs.security.signature.in.list.properties"; + private static final String RSSEC_SIGNATURE_LIST_PROPS = "rs.security.signature.list.properties"; + + private List<JwsSignatureVerifier> sigVerifiers; + private String defaultMediaType; + + public void setSignatureVerifier(JwsSignatureVerifier signatureVerifier) { + setSignatureVerifiers(Collections.singletonList(signatureVerifier)); + } + public void setSignatureVerifiers(List<JwsSignatureVerifier> signatureVerifiers) { + this.sigVerifiers = signatureVerifiers; + } + + protected List<JwsSignatureVerifier> getInitializedSigVerifiers() { + if (sigVerifiers != null) { + return sigVerifiers; + } + Message m = JAXRSUtils.getCurrentMessage(); + Object propLocsProp = + MessageUtils.getContextualProperty(m, RSSEC_SIGNATURE_IN_LIST_PROPS, RSSEC_SIGNATURE_LIST_PROPS); + if (propLocsProp == null) { + throw new SecurityException(); + } + List<String> propLocs = null; + if (propLocsProp instanceof String) { + propLocs = Collections.singletonList((String)propLocsProp); + } else { + propLocs = CastUtils.cast((List<?>)propLocsProp); + } + List<JwsSignatureVerifier> theSigVerifiers = new LinkedList<JwsSignatureVerifier>(); + for (String propLoc : propLocs) { + theSigVerifiers.add(JwsUtils.loadSignatureVerifier(propLoc, m)); + } + return theSigVerifiers; + } + + public String getDefaultMediaType() { + return defaultMediaType; + } + + public void setDefaultMediaType(String defaultMediaType) { + this.defaultMediaType = defaultMediaType; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonWriterProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonWriterProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonWriterProvider.java new file mode 100644 index 0000000..6aa9695 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsJsonWriterProvider.java @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jaxrs; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.helpers.IOUtils; +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.jws.JwsJsonProducer; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; +import org.apache.cxf.rs.security.jose.jws.JwsUtils; + +public class AbstractJwsJsonWriterProvider { + private static final String RSSEC_SIGNATURE_OUT_LIST_PROPS = "rs.security.signature.out.list.properties"; + private static final String RSSEC_SIGNATURE_LIST_PROPS = "rs.security.signature.list.properties"; + + private List<JwsSignatureProvider> sigProviders; + + public void setSignatureProvider(JwsSignatureProvider signatureProvider) { + setSignatureProviders(Collections.singletonList(signatureProvider)); + } + public void setSignatureProviders(List<JwsSignatureProvider> signatureProviders) { + this.sigProviders = signatureProviders; + } + + protected List<JwsSignatureProvider> getInitializedSigProviders() { + if (sigProviders != null) { + return sigProviders; + } + Message m = JAXRSUtils.getCurrentMessage(); + Object propLocsProp = + MessageUtils.getContextualProperty(m, RSSEC_SIGNATURE_OUT_LIST_PROPS, RSSEC_SIGNATURE_LIST_PROPS); + if (propLocsProp == null) { + throw new SecurityException(); + } + List<String> propLocs = null; + if (propLocsProp instanceof String) { + propLocs = Collections.singletonList((String)propLocsProp); + } else { + propLocs = CastUtils.cast((List<?>)propLocsProp); + } + List<JwsSignatureProvider> theSigProviders = new LinkedList<JwsSignatureProvider>(); + for (String propLoc : propLocs) { + theSigProviders.add(JwsUtils.loadSignatureProvider(propLoc, m)); + } + return theSigProviders; + } + protected void writeJws(JwsJsonProducer p, OutputStream os) + throws IOException { + byte[] bytes = StringUtils.toBytesUTF8(p.getJwsJsonSignedDocument()); + IOUtils.copy(new ByteArrayInputStream(bytes), os); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java index 6902e97..6027e60 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java @@ -18,25 +18,15 @@ */ package org.apache.cxf.rs.security.jose.jaxrs; -import java.security.interfaces.RSAPublicKey; -import java.util.Properties; - -import org.apache.cxf.Bus; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; -import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; -import org.apache.cxf.rs.security.jose.jwk.JwkUtils; import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; import org.apache.cxf.rs.security.jose.jws.JwsUtils; -import org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier; public class AbstractJwsReaderProvider { private static final String RSSEC_SIGNATURE_IN_PROPS = "rs.security.signature.in.properties"; private static final String RSSEC_SIGNATURE_PROPS = "rs.security.signature.properties"; - private static final String JSON_WEB_SIGNATURE_ALGO_PROP = "rs.security.jws.content.signature.algorithm"; - private JwsSignatureVerifier sigVerifier; private String defaultMediaType; @@ -56,26 +46,7 @@ public class AbstractJwsReaderProvider { if (propLoc == null) { throw new SecurityException(); } - Bus bus = m.getExchange().getBus(); - try { - Properties props = ResourceUtils.loadProperties(propLoc, bus); - JwsSignatureVerifier theVerifier = null; - String rsaSignatureAlgo = null; - if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_VERIFY); - rsaSignatureAlgo = getSignatureAlgo(props, jwk.getAlgorithm()); - theVerifier = JwsUtils.getSignatureVerifier(jwk, rsaSignatureAlgo); - - } else { - theVerifier = new PublicKeyJwsSignatureVerifier( - (RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props)); - } - return theVerifier; - } catch (SecurityException ex) { - throw ex; - } catch (Exception ex) { - throw new SecurityException(ex); - } + return JwsUtils.loadSignatureVerifier(propLoc, m); } public String getDefaultMediaType() { @@ -86,7 +57,4 @@ public class AbstractJwsReaderProvider { this.defaultMediaType = defaultMediaType; } - private String getSignatureAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_SIGNATURE_ALGO_PROP) : algo; - } } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java index 8f5b1a0..ff0a5aa 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java @@ -21,27 +21,20 @@ package org.apache.cxf.rs.security.jose.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; -import java.security.interfaces.RSAPrivateKey; -import java.util.Properties; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.rs.security.jose.JoseHeaders; -import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; -import org.apache.cxf.rs.security.jose.jwk.JwkUtils; import org.apache.cxf.rs.security.jose.jws.JwsCompactProducer; import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; import org.apache.cxf.rs.security.jose.jws.JwsUtils; -import org.apache.cxf.rs.security.jose.jws.PrivateKeyJwsSignatureProvider; public class AbstractJwsWriterProvider { private static final String RSSEC_SIGNATURE_OUT_PROPS = "rs.security.signature.out.properties"; private static final String RSSEC_SIGNATURE_PROPS = "rs.security.signature.properties"; - private static final String JSON_WEB_SIGNATURE_ALGO_PROP = "rs.security.jws.content.signature.algorithm"; private JwsSignatureProvider sigProvider; @@ -59,30 +52,9 @@ public class AbstractJwsWriterProvider { if (propLoc == null) { throw new SecurityException(); } - try { - Properties props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); - JwsSignatureProvider theSigProvider = null; - String rsaSignatureAlgo = null; - if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_SIGN); - rsaSignatureAlgo = getSignatureAlgo(props, jwk.getAlgorithm()); - theSigProvider = JwsUtils.getSignatureProvider(jwk, rsaSignatureAlgo); - } else { - rsaSignatureAlgo = getSignatureAlgo(props, null); - RSAPrivateKey pk = (RSAPrivateKey)KeyManagementUtils.loadPrivateKey(m, props, - KeyManagementUtils.RSSEC_SIG_KEY_PSWD_PROVIDER); - theSigProvider = new PrivateKeyJwsSignatureProvider(pk, rsaSignatureAlgo); - } - if (theSigProvider == null) { - throw new SecurityException(); - } - headers.setAlgorithm(rsaSignatureAlgo); - return theSigProvider; - } catch (SecurityException ex) { - throw ex; - } catch (Exception ex) { - throw new SecurityException(ex); - } + JwsSignatureProvider theSigProvider = JwsUtils.loadSignatureProvider(propLoc, m); + headers.setAlgorithm(theSigProvider.getAlgorithm()); + return theSigProvider; } protected void writeJws(JwsCompactProducer p, JwsSignatureProvider theSigProvider, OutputStream os) throws IOException { @@ -90,7 +62,5 @@ public class AbstractJwsWriterProvider { byte[] bytes = StringUtils.toBytesUTF8(p.getSignedEncodedJws()); IOUtils.copy(new ByteArrayInputStream(bytes), os); } - private String getSignatureAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_SIGNATURE_ALGO_PROP) : algo; - } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java index 10f82e3..9ae670e 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java @@ -21,8 +21,6 @@ package org.apache.cxf.rs.security.jose.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; -import java.security.interfaces.RSAPublicKey; -import java.util.Properties; import java.util.zip.DeflaterOutputStream; import javax.annotation.Priority; @@ -31,41 +29,25 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.WriterInterceptor; import javax.ws.rs.ext.WriterInterceptorContext; -import org.apache.cxf.Bus; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.rs.security.jose.JoseConstants; import org.apache.cxf.rs.security.jose.JoseHeadersReaderWriter; import org.apache.cxf.rs.security.jose.JoseHeadersWriter; -import org.apache.cxf.rs.security.jose.jwa.Algorithm; -import org.apache.cxf.rs.security.jose.jwe.AesCbcHmacJweEncryption; -import org.apache.cxf.rs.security.jose.jwe.AesGcmContentEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.ContentEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweEncryption; import org.apache.cxf.rs.security.jose.jwe.JweCompactProducer; import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider; import org.apache.cxf.rs.security.jose.jwe.JweEncryptionState; -import org.apache.cxf.rs.security.jose.jwe.JweHeaders; import org.apache.cxf.rs.security.jose.jwe.JweOutputStream; import org.apache.cxf.rs.security.jose.jwe.JweUtils; -import org.apache.cxf.rs.security.jose.jwe.KeyEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.RSAOaepKeyEncryptionAlgorithm; -import org.apache.cxf.rs.security.jose.jwe.WrappedKeyJweEncryption; -import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; -import org.apache.cxf.rs.security.jose.jwk.JwkUtils; @Priority(Priorities.JWE_WRITE_PRIORITY) public class JweWriterInterceptor implements WriterInterceptor { private static final String RSSEC_ENCRYPTION_OUT_PROPS = "rs.security.encryption.out.properties"; private static final String RSSEC_ENCRYPTION_PROPS = "rs.security.encryption.properties"; - private static final String JSON_WEB_ENCRYPTION_CEK_ALGO_PROP = "rs.security.jwe.content.encryption.algorithm"; - private static final String JSON_WEB_ENCRYPTION_KEY_ALGO_PROP = "rs.security.jwe.key.encryption.algorithm"; - private static final String JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP = "rs.security.jwe.zip.algorithm"; private JweEncryptionProvider encryptionProvider; private boolean contentTypeRequired = true; private boolean useJweOutputStream; @@ -89,7 +71,7 @@ public class JweWriterInterceptor implements WriterInterceptor { } } - ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE_JSON)); + ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE)); if (useJweOutputStream) { JweEncryptionState encryption = theEncryptionProvider.createJweEncryptionState(ctString); try { @@ -131,62 +113,9 @@ public class JweWriterInterceptor implements WriterInterceptor { if (propLoc == null) { throw new SecurityException(); } - Bus bus = m.getExchange().getBus(); - try { - KeyEncryptionAlgorithm keyEncryptionProvider = null; - String keyEncryptionAlgo = null; - Properties props = ResourceUtils.loadProperties(propLoc, bus); - String contentEncryptionAlgo = props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP); - ContentEncryptionAlgorithm ctEncryptionProvider = null; - if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_ENCRYPT); - keyEncryptionAlgo = getKeyEncryptionAlgo(props, jwk.getAlgorithm()); - if ("direct".equals(keyEncryptionAlgo)) { - contentEncryptionAlgo = getContentEncryptionAlgo(props, jwk.getAlgorithm()); - ctEncryptionProvider = JweUtils.getContentEncryptionAlgorithm(jwk, contentEncryptionAlgo); - } else { - keyEncryptionProvider = JweUtils.getKeyEncryptionAlgorithm(jwk, keyEncryptionAlgo); - } - - } else { - keyEncryptionProvider = new RSAOaepKeyEncryptionAlgorithm( - (RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props), - getKeyEncryptionAlgo(props, keyEncryptionAlgo)); - } - if (keyEncryptionProvider == null && ctEncryptionProvider == null) { - throw new SecurityException(); - } - - - JweHeaders headers = new JweHeaders(getKeyEncryptionAlgo(props, keyEncryptionAlgo), - contentEncryptionAlgo); - String compression = props.getProperty(JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP); - if (compression != null) { - headers.setZipAlgorithm(compression); - } - if (keyEncryptionProvider != null) { - if (Algorithm.isAesCbcHmac(contentEncryptionAlgo)) { - return new AesCbcHmacJweEncryption(contentEncryptionAlgo, keyEncryptionProvider); - } else { - return new WrappedKeyJweEncryption(headers, - keyEncryptionProvider, - new AesGcmContentEncryptionAlgorithm(contentEncryptionAlgo)); - } - } else { - return new DirectKeyJweEncryption(ctEncryptionProvider); - } - } catch (SecurityException ex) { - throw ex; - } catch (Exception ex) { - throw new SecurityException(ex); - } - } - private String getKeyEncryptionAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_KEY_ALGO_PROP) : algo; - } - private String getContentEncryptionAlgo(Properties props, String algo) { - return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP) : algo; + return JweUtils.loadEncryptionProvider(propLoc, m); } + public void setUseJweOutputStream(boolean useJweOutputStream) { this.useJweOutputStream = useJweOutputStream; } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java new file mode 100644 index 0000000..273aba1 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonClientResponseFilter.java @@ -0,0 +1,57 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +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; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; + +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.rs.security.jose.JoseUtils; +import org.apache.cxf.rs.security.jose.jws.JwsJsonConsumer; +import org.apache.cxf.rs.security.jose.jws.JwsJsonSignatureEntry; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; + +@Priority(Priorities.JWS_CLIENT_READ_PRIORITY) +public class JwsJsonClientResponseFilter extends AbstractJwsJsonReaderProvider implements ClientResponseFilter { + @Override + public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException { + List<JwsSignatureVerifier> theSigVerifiers = getInitializedSigVerifiers(); + JwsJsonConsumer p = new JwsJsonConsumer(IOUtils.readStringFromStream(res.getEntityStream())); + if (!p.verifySignatureWith(theSigVerifiers)) { + throw new SecurityException(); + } + byte[] bytes = p.getDecodedJwsPayloadBytes(); + res.setEntityStream(new ByteArrayInputStream(bytes)); + res.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); + + // the list is guaranteed to be non-empty + JwsJsonSignatureEntry sigEntry = p.getSignatureEntries().get(0); + String ct = JoseUtils.checkContentType(sigEntry.getUnionHeader().getContentType(), getDefaultMediaType()); + if (ct != null) { + res.getHeaders().putSingle("Content-Type", ct); + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java new file mode 100644 index 0000000..6b7ffdf --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonContainerRequestFilter.java @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +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.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; + +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.jaxrs.utils.JAXRSUtils; +import org.apache.cxf.rs.security.jose.JoseUtils; +import org.apache.cxf.rs.security.jose.jws.JwsJsonConsumer; +import org.apache.cxf.rs.security.jose.jws.JwsJsonSignatureEntry; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; + +@PreMatching +@Priority(Priorities.JWS_SERVER_READ_PRIORITY) +public class JwsJsonContainerRequestFilter extends AbstractJwsJsonReaderProvider implements ContainerRequestFilter { + @Override + public void filter(ContainerRequestContext context) throws IOException { + + List<JwsSignatureVerifier> theSigVerifiers = getInitializedSigVerifiers(); + JwsJsonConsumer p = new JwsJsonConsumer(IOUtils.readStringFromStream(context.getEntityStream())); + if (!p.verifySignatureWith(theSigVerifiers)) { + context.abortWith(JAXRSUtils.toResponse(400)); + return; + } + byte[] bytes = p.getDecodedJwsPayloadBytes(); + context.setEntityStream(new ByteArrayInputStream(bytes)); + context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); + + // the list is guaranteed to be non-empty + JwsJsonSignatureEntry sigEntry = p.getSignatureEntries().get(0); + String ct = JoseUtils.checkContentType(sigEntry.getUnionHeader().getContentType(), getDefaultMediaType()); + if (ct != null) { + context.getHeaders().putSingle("Content-Type", ct); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonWriterInterceptor.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonWriterInterceptor.java new file mode 100644 index 0000000..e812e59 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJsonWriterInterceptor.java @@ -0,0 +1,80 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jaxrs; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +import org.apache.cxf.io.CachedOutputStream; +import org.apache.cxf.jaxrs.utils.JAXRSUtils; +import org.apache.cxf.rs.security.jose.JoseConstants; +import org.apache.cxf.rs.security.jose.JoseHeaders; +import org.apache.cxf.rs.security.jose.jws.JwsJsonProducer; +import org.apache.cxf.rs.security.jose.jws.JwsJsonProtectedHeader; +import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; + +@Priority(Priorities.JWS_WRITE_PRIORITY) +public class JwsJsonWriterInterceptor extends AbstractJwsJsonWriterProvider implements WriterInterceptor { + private boolean contentTypeRequired = true; + @Override + public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { + + List<JwsSignatureProvider> sigProviders = getInitializedSigProviders(); + OutputStream actualOs = ctx.getOutputStream(); + CachedOutputStream cos = new CachedOutputStream(); + ctx.setOutputStream(cos); + ctx.proceed(); + JwsJsonProducer p = new JwsJsonProducer(new String(cos.getBytes(), "UTF-8")); + for (JwsSignatureProvider signer : sigProviders) { + JoseHeaders headers = new JoseHeaders(); + headers.setAlgorithm(signer.getAlgorithm()); + setContentTypeIfNeeded(headers, ctx); + //TODO: support setting public JWK kid property as the unprotected header; + // the property would have to be associated with the individual signer + p.signWith(signer, new JwsJsonProtectedHeader(headers), null); + } + ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE_JSON)); + writeJws(p, actualOs); + } + + public void setContentTypeRequired(boolean contentTypeRequired) { + this.contentTypeRequired = contentTypeRequired; + } + + private void setContentTypeIfNeeded(JoseHeaders headers, WriterInterceptorContext ctx) { + if (contentTypeRequired) { + MediaType mt = ctx.getMediaType(); + if (mt != null + && !JAXRSUtils.mediaTypeToString(mt).equals(JoseConstants.MEDIA_TYPE_JOSE_JSON)) { + if ("application".equals(mt.getType())) { + headers.setContentType(mt.getSubtype()); + } else { + headers.setContentType(JAXRSUtils.mediaTypeToString(mt)); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java index ddcaa56..5a42b8d 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsWriterInterceptor.java @@ -51,7 +51,7 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W JoseHeaders headers = new JoseHeaders(); JwsSignatureProvider sigProvider = getInitializedSigProvider(headers); setContentTypeIfNeeded(headers, ctx); - ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE_JSON)); + ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE)); OutputStream actualOs = ctx.getOutputStream(); if (useJwsOutputStream) { JwsSignature jwsSignature = sigProvider.createJwsSignature(headers); @@ -88,7 +88,7 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W if (contentTypeRequired) { MediaType mt = ctx.getMediaType(); if (mt != null - && !JAXRSUtils.mediaTypeToString(mt).equals(JoseConstants.MEDIA_TYPE_JOSE_JSON)) { + && !JAXRSUtils.mediaTypeToString(mt).equals(JoseConstants.MEDIA_TYPE_JOSE)) { if ("application".equals(mt.getType())) { headers.setContentType(mt.getSubtype()); } else { http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwa/Algorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwa/Algorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwa/Algorithm.java index 89ac29d..6c66825 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwa/Algorithm.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwa/Algorithm.java @@ -19,8 +19,11 @@ package org.apache.cxf.rs.security.jose.jwa; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.apache.cxf.rs.security.jose.JoseConstants; @@ -79,6 +82,16 @@ public enum Algorithm { public static final String AES_GCM_ALGO_JAVA = "AES/GCM/NoPadding"; public static final String AES_CBC_ALGO_JAVA = "AES/CBC/PKCS7Padding"; + public static final Set<String> HMAC_SIGN_SET = new HashSet<String>(Arrays.asList(JoseConstants.HMAC_SHA_256_ALGO, + JoseConstants.HMAC_SHA_384_ALGO, + JoseConstants.HMAC_SHA_512_ALGO)); + public static final Set<String> RSA_SHA_SIGN_SET = new HashSet<String>(Arrays.asList(JoseConstants.RS_SHA_256_ALGO, + JoseConstants.RS_SHA_384_ALGO, + JoseConstants.RS_SHA_512_ALGO)); + public static final Set<String> EC_SHA_SIGN_SET = new HashSet<String>(Arrays.asList(JoseConstants.ES_SHA_256_ALGO, + JoseConstants.ES_SHA_384_ALGO, + JoseConstants.ES_SHA_512_ALGO)); + private static final Map<String, String> JAVA_TO_JWT_NAMES; private static final Map<String, String> JWT_TO_JAVA_NAMES; static { @@ -210,18 +223,13 @@ public enum Algorithm { || JoseConstants.A256CBC_HS512_ALGO.equals(algo); } public static boolean isHmacSign(String algo) { - return JoseConstants.HMAC_SHA_256_ALGO.equals(algo) - || JoseConstants.HMAC_SHA_384_ALGO.equals(algo) - || JoseConstants.HMAC_SHA_512_ALGO.equals(algo); + return HMAC_SIGN_SET.contains(algo); } + public static boolean isRsaShaSign(String algo) { - return JoseConstants.RS_SHA_256_ALGO.equals(algo) - || JoseConstants.RS_SHA_384_ALGO.equals(algo) - || JoseConstants.RS_SHA_512_ALGO.equals(algo); + return RSA_SHA_SIGN_SET.contains(algo); } public static boolean isEcDsaSign(String algo) { - return JoseConstants.ES_SHA_256_ALGO.equals(algo) - || JoseConstants.ES_SHA_384_ALGO.equals(algo) - || JoseConstants.ES_SHA_512_ALGO.equals(algo); + return EC_SHA_SIGN_SET.contains(algo); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java index 483ff52..4158da6 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -18,13 +18,23 @@ */ package org.apache.cxf.rs.security.jose.jwe; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Properties; + import javax.crypto.SecretKey; +import org.apache.cxf.jaxrs.utils.ResourceUtils; +import org.apache.cxf.message.Message; +import org.apache.cxf.rs.security.jose.jaxrs.KeyManagementUtils; import org.apache.cxf.rs.security.jose.jwa.Algorithm; import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; import org.apache.cxf.rs.security.jose.jwk.JwkUtils; public final class JweUtils { + private static final String JSON_WEB_ENCRYPTION_CEK_ALGO_PROP = "rs.security.jwe.content.encryption.algorithm"; + private static final String JSON_WEB_ENCRYPTION_KEY_ALGO_PROP = "rs.security.jwe.key.encryption.algorithm"; + private static final String JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP = "rs.security.jwe.zip.algorithm"; private JweUtils() { } @@ -94,4 +104,99 @@ public final class JweUtils { } return null; } + public static JweEncryptionProvider loadEncryptionProvider(String propLoc, Message m) { + KeyEncryptionAlgorithm keyEncryptionProvider = null; + String keyEncryptionAlgo = null; + Properties props = null; + try { + props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + + String contentEncryptionAlgo = props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP); + ContentEncryptionAlgorithm ctEncryptionProvider = null; + if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { + JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_ENCRYPT); + keyEncryptionAlgo = getKeyEncryptionAlgo(props, jwk.getAlgorithm()); + if ("direct".equals(keyEncryptionAlgo)) { + contentEncryptionAlgo = getContentEncryptionAlgo(props, jwk.getAlgorithm()); + ctEncryptionProvider = JweUtils.getContentEncryptionAlgorithm(jwk, contentEncryptionAlgo); + } else { + keyEncryptionProvider = JweUtils.getKeyEncryptionAlgorithm(jwk, keyEncryptionAlgo); + } + + } else { + keyEncryptionProvider = new RSAOaepKeyEncryptionAlgorithm( + (RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props), + getKeyEncryptionAlgo(props, keyEncryptionAlgo)); + } + if (keyEncryptionProvider == null && ctEncryptionProvider == null) { + throw new SecurityException(); + } + + + JweHeaders headers = new JweHeaders(getKeyEncryptionAlgo(props, keyEncryptionAlgo), + contentEncryptionAlgo); + String compression = props.getProperty(JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP); + if (compression != null) { + headers.setZipAlgorithm(compression); + } + if (keyEncryptionProvider != null) { + if (Algorithm.isAesCbcHmac(contentEncryptionAlgo)) { + return new AesCbcHmacJweEncryption(contentEncryptionAlgo, keyEncryptionProvider); + } else { + return new WrappedKeyJweEncryption(headers, + keyEncryptionProvider, + new AesGcmContentEncryptionAlgorithm(contentEncryptionAlgo)); + } + } else { + return new DirectKeyJweEncryption(ctEncryptionProvider); + } + } + public static JweDecryptionProvider loadDecryptionProvider(String propLoc, Message m) { + KeyDecryptionAlgorithm keyDecryptionProvider = null; + Properties props = null; + try { + props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + String contentEncryptionAlgo = props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP); + SecretKey ctDecryptionKey = null; + if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { + JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_ENCRYPT); + String keyEncryptionAlgo = getKeyEncryptionAlgo(props, jwk.getAlgorithm()); + if ("direct".equals(keyEncryptionAlgo)) { + contentEncryptionAlgo = getContentEncryptionAlgo(props, contentEncryptionAlgo); + ctDecryptionKey = JweUtils.getContentDecryptionSecretKey(jwk, contentEncryptionAlgo); + } else { + keyDecryptionProvider = JweUtils.getKeyDecryptionAlgorithm(jwk, keyEncryptionAlgo); + } + } else { + keyDecryptionProvider = new RSAOaepKeyDecryptionAlgorithm( + (RSAPrivateKey)KeyManagementUtils.loadPrivateKey( + m, props, KeyManagementUtils.RSSEC_DECRYPT_KEY_PSWD_PROVIDER)); + } + if (keyDecryptionProvider == null && ctDecryptionKey == null) { + throw new SecurityException(); + } + if (keyDecryptionProvider != null) { + if (Algorithm.isAesCbcHmac(contentEncryptionAlgo)) { + return new AesCbcHmacJweDecryption(keyDecryptionProvider, contentEncryptionAlgo); + } else { + return new WrappedKeyJweDecryption(keyDecryptionProvider, + new AesGcmContentDecryptionAlgorithm(contentEncryptionAlgo)); + } + } else { + return new DirectKeyJweDecryption(ctDecryptionKey, + new AesGcmContentDecryptionAlgorithm(contentEncryptionAlgo)); + } + } + private static String getKeyEncryptionAlgo(Properties props, String algo) { + return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_KEY_ALGO_PROP) : algo; + } + private static String getContentEncryptionAlgo(Properties props, String algo) { + return algo == null ? props.getProperty(JSON_WEB_ENCRYPTION_CEK_ALGO_PROP) : algo; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java index f22bb89..b44ecc8 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java @@ -20,10 +20,14 @@ package org.apache.cxf.rs.security.jose.jws; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.jaxrs.provider.json.JsonMapObject; import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter; import org.apache.cxf.rs.security.jose.JoseUtils; @@ -47,26 +51,29 @@ public class JwsJsonConsumer { private void prepare() { JsonMapObject jsonObject = new JsonMapObject(); new JsonMapObjectReaderWriter().fromJson(jsonObject, jwsSignedDocument); - this.encodedJwsPayload = (String)jsonObject.asMap().get("payload"); + encodedJwsPayload = (String)jsonObject.asMap().get("payload"); + if (encodedJwsPayload == null) { + throw new SecurityException("Invalid JWS JSON sequence: no payload is available"); + } - @SuppressWarnings("unchecked") - List<Map<String, Object>> signatureArray = - (List<Map<String, Object>>)jsonObject.asMap().get("signatures"); + List<Map<String, Object>> signatureArray = CastUtils.cast((List<?>)jsonObject.asMap().get("signatures")); this.signatureEntries = new ArrayList<JwsJsonSignatureEntry>(signatureArray.size()); for (Map<String, Object> signatureEntry : signatureArray) { String protectedHeader = (String)signatureEntry.get("protected"); - @SuppressWarnings("unchecked") - Map<String, Object> header = (Map<String, Object>)signatureEntry.get("header"); + Map<String, Object> header = CastUtils.cast((Map<?, ?>)signatureEntry.get("header")); String signature = (String)signatureEntry.get("signature"); JwsJsonSignatureEntry signatureObject = new JwsJsonSignatureEntry(encodedJwsPayload, protectedHeader, signature, - new JwsJsonUnprotectedHeader(header)); + header != null ? new JwsJsonUnprotectedHeader(header) : null); this.signatureEntries.add(signatureObject); } + if (signatureEntries.isEmpty()) { + throw new SecurityException("Invalid JWS JSON sequence: no signatures are available"); + } } public String getSignedDocument() { return this.jwsSignedDocument; @@ -83,6 +90,9 @@ public class JwsJsonConsumer { public List<JwsJsonSignatureEntry> getSignatureEntries() { return Collections.unmodifiableList(signatureEntries); } + public MultivaluedMap<String, JwsJsonSignatureEntry> getSignatureEntryMap() { + return JwsUtils.getJwsJsonSignatureMap(signatureEntries); + } public boolean verifySignatureWith(JwsSignatureVerifier validator) { for (JwsJsonSignatureEntry signatureEntry : signatureEntries) { if (signatureEntry.verifySignatureWith(validator)) { @@ -91,6 +101,45 @@ public class JwsJsonConsumer { } return false; } + public boolean verifySignatureWith(List<JwsSignatureVerifier> validators) { + try { + verifyAndGetNonValidated(validators); + return true; + } catch (SecurityException ex) { + return false; + } + } + public List<JwsJsonSignatureEntry> verifyAndGetNonValidated(List<JwsSignatureVerifier> validators) { + if (validators.size() > signatureEntries.size()) { + throw new SecurityException("Too many signature validators"); + } + // TODO: more effective approach is needed + List<JwsJsonSignatureEntry> validatedSignatures = new LinkedList<JwsJsonSignatureEntry>(); + for (JwsSignatureVerifier validator : validators) { + boolean validated = false; + for (JwsJsonSignatureEntry sigEntry : signatureEntries) { + if (sigEntry.verifySignatureWith(validator)) { + validatedSignatures.add(sigEntry); + validated = true; + break; + } + } + if (!validated) { + throw new SecurityException(); + } + } + if (validatedSignatures.isEmpty()) { + throw new SecurityException(); + } + List<JwsJsonSignatureEntry> nonValidatedSignatures = new LinkedList<JwsJsonSignatureEntry>(); + for (JwsJsonSignatureEntry sigEntry : signatureEntries) { + if (!validatedSignatures.contains(sigEntry)) { + nonValidatedSignatures.add(sigEntry); + } + } + return nonValidatedSignatures; + } + public boolean verifySignatureWith(JsonWebKey key) { return verifySignatureWith(JwsUtils.getSignatureVerifier(key)); } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java index 740ded1..b43dc40 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java @@ -22,6 +22,8 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.cxf.common.util.Base64UrlUtility; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.rs.security.jose.JoseHeaders; @@ -58,6 +60,15 @@ public class JwsJsonProducer { public List<JwsJsonSignatureEntry> getSignatureEntries() { return Collections.unmodifiableList(signatures); } + public MultivaluedMap<String, JwsJsonSignatureEntry> getSignatureEntryMap() { + return JwsUtils.getJwsJsonSignatureMap(signatures); + } + public String signWith(List<JwsSignatureProvider> signers) { + for (JwsSignatureProvider signer : signers) { + signWith(signer); + } + return getJwsJsonSignedDocument(); + } public String signWith(JwsSignatureProvider signer) { JoseHeaders headers = new JoseHeaders(); headers.setAlgorithm(signer.getAlgorithm()); http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java index b9f37b5..a430575 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java @@ -95,6 +95,9 @@ public class JwsJsonSignatureEntry { public String getUnsignedEncodedSequence() { return getEncodedProtectedHeader() + "." + getEncodedJwsPayload(); } + public String getKeyId() { + return getUnionHeader().getKeyId(); + } public boolean verifySignatureWith(JwsSignatureVerifier validator) { try { return validator.verify(getUnionHeader(), http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java index 08c59c1..30e3b8c 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java @@ -18,11 +18,23 @@ */ package org.apache.cxf.rs.security.jose.jws; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.List; +import java.util.Properties; + +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.cxf.jaxrs.impl.MetadataMap; +import org.apache.cxf.jaxrs.utils.ResourceUtils; +import org.apache.cxf.message.Message; +import org.apache.cxf.rs.security.jose.jaxrs.KeyManagementUtils; import org.apache.cxf.rs.security.jose.jwa.Algorithm; import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; import org.apache.cxf.rs.security.jose.jwk.JwkUtils; public final class JwsUtils { + private static final String JSON_WEB_SIGNATURE_ALGO_PROP = "rs.security.jws.content.signature.algorithm"; private JwsUtils() { } @@ -63,5 +75,59 @@ public final class JwsUtils { } return theVerifier; } - + public static MultivaluedMap<String, JwsJsonSignatureEntry> getJwsJsonSignatureMap( + List<JwsJsonSignatureEntry> signatures) { + MultivaluedMap<String, JwsJsonSignatureEntry> map = new MetadataMap<String, JwsJsonSignatureEntry>(); + for (JwsJsonSignatureEntry entry : signatures) { + map.add(entry.getUnionHeader().getAlgorithm(), entry); + } + return map; + } + public static JwsSignatureProvider loadSignatureProvider(String propLoc, Message m) { + Properties props = null; + try { + props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + JwsSignatureProvider theSigProvider = null; + String rsaSignatureAlgo = null; + if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { + JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_SIGN); + rsaSignatureAlgo = getSignatureAlgo(props, jwk.getAlgorithm()); + theSigProvider = JwsUtils.getSignatureProvider(jwk, rsaSignatureAlgo); + } else { + rsaSignatureAlgo = getSignatureAlgo(props, null); + RSAPrivateKey pk = (RSAPrivateKey)KeyManagementUtils.loadPrivateKey(m, props, + KeyManagementUtils.RSSEC_SIG_KEY_PSWD_PROVIDER); + theSigProvider = new PrivateKeyJwsSignatureProvider(pk, rsaSignatureAlgo); + } + if (theSigProvider == null) { + throw new SecurityException(); + } + return theSigProvider; + } + public static JwsSignatureVerifier loadSignatureVerifier(String propLoc, Message m) { + Properties props = null; + try { + props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + JwsSignatureVerifier theVerifier = null; + String rsaSignatureAlgo = null; + if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { + JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_VERIFY); + rsaSignatureAlgo = getSignatureAlgo(props, jwk.getAlgorithm()); + theVerifier = JwsUtils.getSignatureVerifier(jwk, rsaSignatureAlgo); + + } else { + theVerifier = new PublicKeyJwsSignatureVerifier( + (RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props)); + } + return theVerifier; + } + private static String getSignatureAlgo(Properties props, String algo) { + return algo == null ? props.getProperty(JSON_WEB_SIGNATURE_ALGO_PROP) : algo; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java index a79754a..e46b5cd 100644 --- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java +++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java @@ -59,13 +59,13 @@ public class JwsJsonConsumerTest extends Assert { List<JwsJsonSignatureEntry> sigEntries = consumer.getSignatureEntries(); assertEquals(2, sigEntries.size()); // 1st signature - String firstKid = (String)sigEntries.get(0).getUnionHeader().getHeader("kid"); + String firstKid = (String)sigEntries.get(0).getKeyId(); assertEquals(KID_OF_THE_FIRST_SIGNER, firstKid); JsonWebKey rsaKey = jwks.getKey(firstKid); assertNotNull(rsaKey); assertTrue(sigEntries.get(0).verifySignatureWith(rsaKey)); // 2nd signature - String secondKid = (String)sigEntries.get(1).getUnionHeader().getHeader("kid"); + String secondKid = (String)sigEntries.get(1).getKeyId(); assertEquals(KID_OF_THE_SECOND_SIGNER, secondKid); JsonWebKey ecKey = jwks.getKey(secondKid); assertNotNull(ecKey); http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/BookServerJwsJson.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/BookServerJwsJson.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/BookServerJwsJson.java new file mode 100644 index 0000000..3b451e1 --- /dev/null +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/BookServerJwsJson.java @@ -0,0 +1,57 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.systest.jaxrs.security.jwt; + +import org.apache.cxf.Bus; +import org.apache.cxf.BusFactory; +import org.apache.cxf.bus.spring.SpringBusFactory; +import org.apache.cxf.testutil.common.AbstractBusTestServerBase; +import org.apache.cxf.testutil.common.TestUtil; + +public class BookServerJwsJson extends AbstractBusTestServerBase { + public static final String PORT = TestUtil.getPortNumber("jaxrs-jws-json"); + private static final String SERVER_CONFIG_FILE = + "org/apache/cxf/systest/jaxrs/security/jwt/serverJwsJson.xml"; + + protected void run() { + SpringBusFactory bf = new SpringBusFactory(); + Bus springBus = bf.createBus(SERVER_CONFIG_FILE); + BusFactory.setDefaultBus(springBus); + setBus(springBus); + + try { + new BookServerJwsJson(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + try { + BookServerJwsJson s = new BookServerJwsJson(); + s.start(); + } catch (Exception ex) { + ex.printStackTrace(); + System.exit(-1); + } finally { + System.out.println("done!"); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJwsJsonTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJwsJsonTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJwsJsonTest.java new file mode 100644 index 0000000..892ca40 --- /dev/null +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJwsJsonTest.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.systest.jaxrs.security.jwt; + +import java.net.URL; +import java.util.LinkedList; +import java.util.List; + +import org.apache.cxf.Bus; +import org.apache.cxf.bus.spring.SpringBusFactory; +import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; +import org.apache.cxf.rs.security.jose.jaxrs.JwsJsonClientResponseFilter; +import org.apache.cxf.rs.security.jose.jaxrs.JwsJsonWriterInterceptor; +import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class JAXRSJwsJsonTest extends AbstractBusClientServerTestBase { + public static final String PORT = BookServerJwsJson.PORT; + + @BeforeClass + public static void startServers() throws Exception { + assertTrue("server did not launch correctly", + launchServer(BookServerJwsJson.class, true)); + } + + @Test + public void testJwsJwkHMac() throws Exception { + String address = "https://localhost:" + PORT + "/jwsjsonhmac"; + JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = JAXRSJwsJsonTest.class.getResource("client.xml"); + Bus springBus = bf.createBus(busFile.toString()); + bean.setBus(springBus); + bean.setServiceClass(BookStore.class); + bean.setAddress(address); + List<Object> providers = new LinkedList<Object>(); + providers.add(new JwsJsonWriterInterceptor()); + providers.add(new JwsJsonClientResponseFilter()); + bean.setProviders(providers); + bean.getProperties(true).put("rs.security.signature.list.properties", + "org/apache/cxf/systest/jaxrs/security/secret.jwk.properties"); + BookStore bs = bean.create(BookStore.class); + String text = bs.echoText("book"); + assertEquals("book", text); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/e027dc7d/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/serverJwsJson.xml ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/serverJwsJson.xml b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/serverJwsJson.xml new file mode 100644 index 0000000..2e3911d --- /dev/null +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/serverJwsJson.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation=" http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd "> + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> + <cxf:bus> + <cxf:features> + <cxf:logging/> + </cxf:features> + </cxf:bus> + <httpj:engine-factory id="port-9095-tls-config"> + <httpj:engine port="${testutil.ports.jaxrs-jws-json}"> + <httpj:tlsServerParameters> + <sec:keyManagers keyPassword="password"> + <sec:keyStore type="JKS" password="password" file="src/test/java/org/apache/cxf/systest/http/resources/Bethal.jks"/> + </sec:keyManagers> + <sec:trustManagers> + <sec:keyStore type="JKS" password="password" file="src/test/java/org/apache/cxf/systest/http/resources/Truststore.jks"/> + </sec:trustManagers> + <sec:cipherSuitesFilter> + <sec:include>.*_EXPORT_.*</sec:include> + <sec:include>.*_EXPORT1024_.*</sec:include> + <sec:include>.*_WITH_AES_.*</sec:include> + </sec:cipherSuitesFilter> + <sec:clientAuthentication want="true" required="true"/> + </httpj:tlsServerParameters> + </httpj:engine> + </httpj:engine-factory> + + <bean id="serviceBean" class="org.apache.cxf.systest.jaxrs.security.jwt.BookStore"/> + <bean id="jwsInFilter" class="org.apache.cxf.rs.security.jose.jaxrs.JwsJsonContainerRequestFilter"/> + <bean id="jwsOutFilter" class="org.apache.cxf.rs.security.jose.jaxrs.JwsJsonWriterInterceptor"/> + <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-jws-json}/jwsjsonhmac"> + <jaxrs:serviceBeans> + <ref bean="serviceBean"/> + </jaxrs:serviceBeans> + <jaxrs:providers> + <ref bean="jwsInFilter"/> + <ref bean="jwsOutFilter"/> + </jaxrs:providers> + <jaxrs:properties> + <entry key="rs.security.signature.list.properties" value="org/apache/cxf/systest/jaxrs/security/secret.jwk.properties"/> + </jaxrs:properties> + </jaxrs:server> + +</beans>
