You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2014/10/06 19:26:03 UTC
[10/10] git commit: [CXF-5944] Finalizing the current round of
refactorings with introducing a dedicated rt rs security module,
idea from Luigi Lo Iacono
[CXF-5944] Finalizing the current round of refactorings with introducing a dedicated rt rs security module, idea from Luigi Lo Iacono
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/9c053334
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/9c053334
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/9c053334
Branch: refs/heads/master
Commit: 9c053334d1f533d9666042fdc759f0234a4f97ed
Parents: 6129ec5
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Mon Oct 6 18:25:22 2014 +0100
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Mon Oct 6 18:25:22 2014 +0100
----------------------------------------------------------------------
rt/pom.xml | 1 +
rt/rs/security/jose/pom.xml | 58 ++++
.../rs/security/jose/AbstractJoseObject.java | 61 ++++
.../jose/AbstractJoseObjectReaderWriter.java | 230 +++++++++++++++
.../cxf/rs/security/jose/JoseConstants.java | 81 ++++++
.../cxf/rs/security/jose/JoseHeaders.java | 174 ++++++++++++
.../cxf/rs/security/jose/JoseHeadersReader.java | 24 ++
.../security/jose/JoseHeadersReaderWriter.java | 39 +++
.../cxf/rs/security/jose/JoseHeadersWriter.java | 25 ++
.../apache/cxf/rs/security/jose/JoseUtils.java | 46 +++
.../jose/jaxrs/AbstractJweDecryptingFilter.java | 134 +++++++++
.../jose/jaxrs/AbstractJwsReaderProvider.java | 92 ++++++
.../jose/jaxrs/AbstractJwsWriterProvider.java | 94 +++++++
.../jose/jaxrs/JweClientResponseFilter.java | 46 +++
.../jose/jaxrs/JweContainerRequestFilter.java | 46 +++
.../jose/jaxrs/JweWriterInterceptor.java | 200 +++++++++++++
.../jose/jaxrs/JwsClientResponseFilter.java | 52 ++++
.../jose/jaxrs/JwsContainerRequestFilter.java | 56 ++++
.../jose/jaxrs/JwsJwtMessageBodyReader.java | 54 ++++
.../jose/jaxrs/JwsJwtMessageBodyWriter.java | 60 ++++
.../jose/jaxrs/JwsWriterInterceptor.java | 100 +++++++
.../security/jose/jaxrs/KeyManagementUtils.java | 145 ++++++++++
.../cxf/rs/security/jose/jaxrs/Priorities.java | 31 ++
.../jose/jaxrs/PrivateKeyPasswordProvider.java | 25 ++
.../cxf/rs/security/jose/jwa/Algorithm.java | 227 +++++++++++++++
.../jwe/AbstractContentEncryptionAlgorithm.java | 61 ++++
...stractContentEncryptionCipherProperties.java | 39 +++
.../jose/jwe/AbstractJweDecryption.java | 105 +++++++
.../jose/jwe/AbstractJweEncryption.java | 184 ++++++++++++
.../jwe/AbstractWrapKeyEncryptionAlgorithm.java | 100 +++++++
.../jose/jwe/AesCbcHmacJweDecryption.java | 89 ++++++
.../jose/jwe/AesCbcHmacJweEncryption.java | 188 +++++++++++++
.../jwe/AesGcmContentDecryptionAlgorithm.java | 44 +++
.../jwe/AesGcmContentEncryptionAlgorithm.java | 50 ++++
.../jwe/AesGcmWrapKeyDecryptionAlgorithm.java | 72 +++++
.../jwe/AesGcmWrapKeyEncryptionAlgorithm.java | 64 +++++
.../jose/jwe/AesWrapKeyDecryptionAlgorithm.java | 53 ++++
.../jose/jwe/AesWrapKeyEncryptionAlgorithm.java | 48 ++++
.../jose/jwe/AuthenticationTagProducer.java | 24 ++
.../jose/jwe/ContentDecryptionAlgorithm.java | 24 ++
.../jose/jwe/ContentEncryptionAlgorithm.java | 27 ++
.../jwe/ContentEncryptionCipherProperties.java | 27 ++
.../jose/jwe/DirectKeyDecryptionAlgorithm.java | 39 +++
.../jose/jwe/DirectKeyEncryptionAlgorithm.java | 34 +++
.../jose/jwe/DirectKeyJweDecryption.java | 38 +++
.../jose/jwe/DirectKeyJweEncryption.java | 41 +++
.../security/jose/jwe/JweCompactConsumer.java | 113 ++++++++
.../security/jose/jwe/JweCompactProducer.java | 156 +++++++++++
.../security/jose/jwe/JweDecryptionOutput.java | 43 +++
.../jose/jwe/JweDecryptionProvider.java | 26 ++
.../jose/jwe/JweEncryptionProvider.java | 26 ++
.../security/jose/jwe/JweEncryptionState.java | 63 +++++
.../cxf/rs/security/jose/jwe/JweHeaders.java | 106 +++++++
.../rs/security/jose/jwe/JweOutputStream.java | 145 ++++++++++
.../cxf/rs/security/jose/jwe/JweUtils.java | 97 +++++++
.../jose/jwe/KeyDecryptionAlgorithm.java | 24 ++
.../jose/jwe/KeyEncryptionAlgorithm.java | 25 ++
.../PbesHmacAesWrapKeyDecryptionAlgorithm.java | 54 ++++
.../PbesHmacAesWrapKeyEncryptionAlgorithm.java | 173 ++++++++++++
.../jose/jwe/RSAOaepKeyDecryptionAlgorithm.java | 45 +++
.../jose/jwe/RSAOaepKeyEncryptionAlgorithm.java | 39 +++
.../jose/jwe/WrappedKeyDecryptionAlgorithm.java | 85 ++++++
.../jose/jwe/WrappedKeyJweDecryption.java | 34 +++
.../jose/jwe/WrappedKeyJweEncryption.java | 47 ++++
.../jose/jwk/DefaultJwkReaderWriter.java | 48 ++++
.../cxf/rs/security/jose/jwk/JsonWebKey.java | 160 +++++++++++
.../cxf/rs/security/jose/jwk/JsonWebKeys.java | 131 +++++++++
.../rs/security/jose/jwk/JwkReaderWriter.java | 27 ++
.../cxf/rs/security/jose/jwk/JwkUtils.java | 280 +++++++++++++++++++
.../jose/jws/AbstractJwsSignatureProvider.java | 59 ++++
.../jose/jws/EcDsaJwsSignatureProvider.java | 42 +++
.../jose/jws/EcDsaJwsSignatureVerifier.java | 40 +++
.../jose/jws/HmacJwsSignatureProvider.java | 75 +++++
.../jose/jws/HmacJwsSignatureVerifier.java | 79 ++++++
.../security/jose/jws/JwsCompactConsumer.java | 118 ++++++++
.../security/jose/jws/JwsCompactProducer.java | 113 ++++++++
.../cxf/rs/security/jose/jws/JwsHeaders.java | 37 +++
.../jose/jws/JwsJwtCompactConsumer.java | 49 ++++
.../jose/jws/JwsJwtCompactProducer.java | 51 ++++
.../rs/security/jose/jws/JwsOutputStream.java | 66 +++++
.../cxf/rs/security/jose/jws/JwsSignature.java | 25 ++
.../security/jose/jws/JwsSignatureProvider.java | 25 ++
.../security/jose/jws/JwsSignatureVerifier.java | 25 ++
.../cxf/rs/security/jose/jws/JwsUtils.java | 67 +++++
.../jws/PrivateKeyJwsSignatureProvider.java | 87 ++++++
.../jose/jws/PublicKeyJwsSignatureVerifier.java | 68 +++++
.../cxf/rs/security/jose/jwt/JwtClaims.java | 102 +++++++
.../cxf/rs/security/jose/jwt/JwtConstants.java | 36 +++
.../cxf/rs/security/jose/jwt/JwtHeaders.java | 53 ++++
.../cxf/rs/security/jose/jwt/JwtToken.java | 45 +++
.../cxf/rs/security/jose/jwt/JwtTokenJson.java | 37 +++
.../rs/security/jose/jwt/JwtTokenReader.java | 27 ++
.../security/jose/jwt/JwtTokenReaderWriter.java | 64 +++++
.../rs/security/jose/jwt/JwtTokenWriter.java | 30 ++
.../jose/jwe/JweCompactReaderWriterTest.java | 211 ++++++++++++++
.../jose/jwe/JwePbeHmacAesWrapTest.java | 80 ++++++
.../rs/security/jose/jwk/JsonWebKeyTest.java | 222 +++++++++++++++
.../cxf/rs/security/jose/jwk/jwkPrivateSet.txt | 23 ++
.../cxf/rs/security/jose/jwk/jwkPublicSet.txt | 17 ++
.../cxf/rs/security/jose/jwk/jwkSecretSet.txt | 13 +
.../security/jose/jws/JwsCompactHeaderTest.java | 147 ++++++++++
.../jose/jws/JwsCompactReaderWriterTest.java | 256 +++++++++++++++++
rt/rs/security/oauth-parent/oauth2-jose/pom.xml | 8 +-
.../rs/security/jose/AbstractJoseObject.java | 61 ----
.../jose/AbstractJoseObjectReaderWriter.java | 230 ---------------
.../cxf/rs/security/jose/JoseConstants.java | 81 ------
.../cxf/rs/security/jose/JoseHeaders.java | 174 ------------
.../cxf/rs/security/jose/JoseHeadersReader.java | 24 --
.../security/jose/JoseHeadersReaderWriter.java | 39 ---
.../cxf/rs/security/jose/JoseHeadersWriter.java | 25 --
.../apache/cxf/rs/security/jose/JoseUtils.java | 46 ---
.../jose/jaxrs/AbstractJweDecryptingFilter.java | 134 ---------
.../jose/jaxrs/AbstractJwsReaderProvider.java | 92 ------
.../jose/jaxrs/AbstractJwsWriterProvider.java | 94 -------
.../jose/jaxrs/JweClientResponseFilter.java | 46 ---
.../jose/jaxrs/JweContainerRequestFilter.java | 46 ---
.../jose/jaxrs/JweWriterInterceptor.java | 200 -------------
.../jose/jaxrs/JwsClientResponseFilter.java | 52 ----
.../jose/jaxrs/JwsContainerRequestFilter.java | 56 ----
.../jose/jaxrs/JwsJwtMessageBodyReader.java | 54 ----
.../jose/jaxrs/JwsJwtMessageBodyWriter.java | 60 ----
.../jose/jaxrs/JwsWriterInterceptor.java | 100 -------
.../security/jose/jaxrs/KeyManagementUtils.java | 145 ----------
.../cxf/rs/security/jose/jaxrs/Priorities.java | 31 --
.../jose/jaxrs/PrivateKeyPasswordProvider.java | 25 --
.../cxf/rs/security/jose/jwa/Algorithm.java | 227 ---------------
.../jwe/AbstractContentEncryptionAlgorithm.java | 61 ----
...stractContentEncryptionCipherProperties.java | 39 ---
.../jose/jwe/AbstractJweDecryption.java | 105 -------
.../jose/jwe/AbstractJweEncryption.java | 184 ------------
.../jwe/AbstractWrapKeyEncryptionAlgorithm.java | 100 -------
.../jose/jwe/AesCbcHmacJweDecryption.java | 89 ------
.../jose/jwe/AesCbcHmacJweEncryption.java | 188 -------------
.../jwe/AesGcmContentDecryptionAlgorithm.java | 44 ---
.../jwe/AesGcmContentEncryptionAlgorithm.java | 50 ----
.../jwe/AesGcmWrapKeyDecryptionAlgorithm.java | 72 -----
.../jwe/AesGcmWrapKeyEncryptionAlgorithm.java | 64 -----
.../jose/jwe/AesWrapKeyDecryptionAlgorithm.java | 53 ----
.../jose/jwe/AesWrapKeyEncryptionAlgorithm.java | 48 ----
.../jose/jwe/AuthenticationTagProducer.java | 24 --
.../jose/jwe/ContentDecryptionAlgorithm.java | 24 --
.../jose/jwe/ContentEncryptionAlgorithm.java | 27 --
.../jwe/ContentEncryptionCipherProperties.java | 27 --
.../jose/jwe/DirectKeyDecryptionAlgorithm.java | 39 ---
.../jose/jwe/DirectKeyEncryptionAlgorithm.java | 34 ---
.../jose/jwe/DirectKeyJweDecryption.java | 38 ---
.../jose/jwe/DirectKeyJweEncryption.java | 41 ---
.../security/jose/jwe/JweCompactConsumer.java | 113 --------
.../security/jose/jwe/JweCompactProducer.java | 156 -----------
.../security/jose/jwe/JweDecryptionOutput.java | 43 ---
.../jose/jwe/JweDecryptionProvider.java | 26 --
.../jose/jwe/JweEncryptionProvider.java | 26 --
.../security/jose/jwe/JweEncryptionState.java | 63 -----
.../cxf/rs/security/jose/jwe/JweHeaders.java | 106 -------
.../rs/security/jose/jwe/JweOutputStream.java | 145 ----------
.../cxf/rs/security/jose/jwe/JweUtils.java | 97 -------
.../jose/jwe/KeyDecryptionAlgorithm.java | 24 --
.../jose/jwe/KeyEncryptionAlgorithm.java | 25 --
.../PbesHmacAesWrapKeyDecryptionAlgorithm.java | 54 ----
.../PbesHmacAesWrapKeyEncryptionAlgorithm.java | 173 ------------
.../jose/jwe/RSAOaepKeyDecryptionAlgorithm.java | 45 ---
.../jose/jwe/RSAOaepKeyEncryptionAlgorithm.java | 39 ---
.../jose/jwe/WrappedKeyDecryptionAlgorithm.java | 85 ------
.../jose/jwe/WrappedKeyJweDecryption.java | 34 ---
.../jose/jwe/WrappedKeyJweEncryption.java | 47 ----
.../jose/jwk/DefaultJwkReaderWriter.java | 48 ----
.../cxf/rs/security/jose/jwk/JsonWebKey.java | 160 -----------
.../cxf/rs/security/jose/jwk/JsonWebKeys.java | 131 ---------
.../rs/security/jose/jwk/JwkReaderWriter.java | 27 --
.../cxf/rs/security/jose/jwk/JwkUtils.java | 280 -------------------
.../jose/jws/AbstractJwsSignatureProvider.java | 59 ----
.../jose/jws/EcDsaJwsSignatureProvider.java | 42 ---
.../jose/jws/EcDsaJwsSignatureVerifier.java | 40 ---
.../jose/jws/HmacJwsSignatureProvider.java | 75 -----
.../jose/jws/HmacJwsSignatureVerifier.java | 79 ------
.../security/jose/jws/JwsCompactConsumer.java | 119 --------
.../security/jose/jws/JwsCompactProducer.java | 113 --------
.../cxf/rs/security/jose/jws/JwsHeaders.java | 37 ---
.../jose/jws/JwsJwtCompactConsumer.java | 49 ----
.../jose/jws/JwsJwtCompactProducer.java | 51 ----
.../rs/security/jose/jws/JwsOutputStream.java | 66 -----
.../cxf/rs/security/jose/jws/JwsSignature.java | 25 --
.../security/jose/jws/JwsSignatureProvider.java | 25 --
.../security/jose/jws/JwsSignatureVerifier.java | 25 --
.../cxf/rs/security/jose/jws/JwsUtils.java | 67 -----
.../jws/PrivateKeyJwsSignatureProvider.java | 87 ------
.../jose/jws/PublicKeyJwsSignatureVerifier.java | 68 -----
.../cxf/rs/security/jose/jwt/JwtClaims.java | 102 -------
.../cxf/rs/security/jose/jwt/JwtConstants.java | 36 ---
.../cxf/rs/security/jose/jwt/JwtHeaders.java | 53 ----
.../cxf/rs/security/jose/jwt/JwtToken.java | 45 ---
.../cxf/rs/security/jose/jwt/JwtTokenJson.java | 37 ---
.../rs/security/jose/jwt/JwtTokenReader.java | 27 --
.../security/jose/jwt/JwtTokenReaderWriter.java | 64 -----
.../rs/security/jose/jwt/JwtTokenWriter.java | 30 --
.../jose/jwe/JweCompactReaderWriterTest.java | 211 --------------
.../jose/jwe/JwePbeHmacAesWrapTest.java | 80 ------
.../rs/security/jose/jwk/JsonWebKeyTest.java | 222 ---------------
.../cxf/rs/security/jose/jwk/jwkPrivateSet.txt | 23 --
.../cxf/rs/security/jose/jwk/jwkPublicSet.txt | 17 --
.../cxf/rs/security/jose/jwk/jwkSecretSet.txt | 13 -
.../security/jose/jws/JwsCompactHeaderTest.java | 147 ----------
.../jose/jws/JwsCompactReaderWriterTest.java | 256 -----------------
.../jose/jwt/grant/JwtUserSubjectTest.java | 32 +++
204 files changed, 7823 insertions(+), 7735 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/pom.xml
----------------------------------------------------------------------
diff --git a/rt/pom.xml b/rt/pom.xml
index db0de04..b5975a6 100644
--- a/rt/pom.xml
+++ b/rt/pom.xml
@@ -63,6 +63,7 @@
<module>rs/extensions/search</module>
<module>rs/security/xml</module>
<module>rs/security/sso/saml</module>
+ <module>rs/security/jose</module>
<module>rs/security/oauth-parent</module>
<module>rs/security/cors</module>
<module>management</module>
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/pom.xml
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/pom.xml b/rt/rs/security/jose/pom.xml
new file mode 100644
index 0000000..2e3c3bb
--- /dev/null
+++ b/rt/rs/security/jose/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-rt-rs-security-jose</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache CXF Runtime JOSE</name>
+ <description>Apache CXF Runtime JOSE</description>
+ <url>http://cxf.apache.org</url>
+ <parent>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-parent</artifactId>
+ <version>3.1.0-SNAPSHOT</version>
+ <relativePath>../../../../parent/pom.xml</relativePath>
+ </parent>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-ext-jdk15on</artifactId>
+ <version>${cxf.bcprov.version}</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <!--test dependencies-->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObject.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObject.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObject.java
new file mode 100644
index 0000000..1db9f1c
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObject.java
@@ -0,0 +1,61 @@
+/**
+ * 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;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public abstract class AbstractJoseObject {
+ protected Map<String, Object> values = new LinkedHashMap<String, Object>();
+
+ protected AbstractJoseObject() {
+
+ }
+
+ protected AbstractJoseObject(Map<String, Object> values) {
+ this.values = values;
+ }
+
+ protected void setValue(String name, Object value) {
+ values.put(name, value);
+ }
+
+ protected Object getValue(String name) {
+ return values.get(name);
+ }
+
+ public Map<String, Object> asMap() {
+ return new LinkedHashMap<String, Object>(values);
+ }
+
+ protected Long getLongDate(String name) {
+ Object object = getValue(name);
+ return object instanceof Long ? (Long)object : Long.valueOf(object.toString());
+ }
+
+ public int hashCode() {
+ return values.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ return obj instanceof AbstractJoseObject && ((AbstractJoseObject)obj).values.equals(this.values);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObjectReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObjectReaderWriter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObjectReaderWriter.java
new file mode 100644
index 0000000..d1cbcb7
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/AbstractJoseObjectReaderWriter.java
@@ -0,0 +1,230 @@
+/**
+ * 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;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+
+
+
+public class AbstractJoseObjectReaderWriter {
+ private static final Set<String> DATE_PROPERTIES =
+ new HashSet<String>(Arrays.asList(JwtConstants.CLAIM_EXPIRY,
+ JwtConstants.CLAIM_ISSUED_AT,
+ JwtConstants.CLAIM_NOT_BEFORE));
+ private boolean format;
+
+ protected String toJson(AbstractJoseObject jwt) {
+ StringBuilder sb = new StringBuilder();
+ toJsonInternal(sb, jwt.asMap());
+ return sb.toString();
+ }
+
+ protected void toJsonInternal(StringBuilder sb, Map<String, Object> map) {
+ sb.append("{");
+ for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext();) {
+ Map.Entry<String, Object> entry = it.next();
+ sb.append("\"").append(entry.getKey()).append("\"");
+ sb.append(":");
+ toJsonInternal(sb, entry.getValue(), it.hasNext());
+ }
+ sb.append("}");
+ }
+
+ protected void toJsonInternal(StringBuilder sb, Object[] array) {
+ toJsonInternal(sb, Arrays.asList(array));
+ }
+
+ protected void toJsonInternal(StringBuilder sb, Collection<?> coll) {
+ sb.append("[");
+ formatIfNeeded(sb);
+ for (Iterator<?> iter = coll.iterator(); iter.hasNext();) {
+ toJsonInternal(sb, iter.next(), iter.hasNext());
+ }
+ formatIfNeeded(sb);
+ sb.append("]");
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void toJsonInternal(StringBuilder sb, Object value, boolean hasNext) {
+ if (AbstractJoseObject.class.isAssignableFrom(value.getClass())) {
+ sb.append(toJson((AbstractJoseObject)value));
+ } else if (value.getClass().isArray()) {
+ toJsonInternal(sb, (Object[])value);
+ } else if (Collection.class.isAssignableFrom(value.getClass())) {
+ toJsonInternal(sb, (Collection<?>)value);
+ } else if (Map.class.isAssignableFrom(value.getClass())) {
+ toJsonInternal(sb, (Map<String, Object>)value);
+ } else {
+ if (value.getClass() == String.class) {
+ sb.append("\"");
+ }
+ sb.append(value);
+ if (value.getClass() == String.class) {
+ sb.append("\"");
+ }
+ }
+ if (hasNext) {
+ sb.append(",");
+ formatIfNeeded(sb);
+ }
+
+ }
+
+ protected void formatIfNeeded(StringBuilder sb) {
+ if (format) {
+ sb.append("\r\n ");
+ }
+ }
+
+ protected void fromJsonInternal(AbstractJoseObject jwt, String json) {
+ String theJson = json.trim();
+ JoseObjectSettable joseObject = new JoseObjectSettable(jwt);
+ readJwtObjectAsMap(joseObject, theJson.substring(1, theJson.length() - 1));
+ }
+
+
+
+ protected void readJwtObjectAsMap(Settable values, String json) {
+ for (int i = 0; i < json.length(); i++) {
+ if (isWhiteSpace(json.charAt(i))) {
+ continue;
+ }
+
+ int closingQuote = json.indexOf('"', i + 1);
+ int from = json.charAt(i) == '"' ? i + 1 : i;
+ String name = json.substring(from, closingQuote);
+ int sepIndex = json.indexOf(':', closingQuote + 1);
+
+ int j = 1;
+ while (isWhiteSpace(json.charAt(sepIndex + j))) {
+ j++;
+ }
+ if (json.charAt(sepIndex + j) == '{') {
+ int closingIndex = getClosingIndex(json, '{', '}', sepIndex + j);
+ String newJson = json.substring(sepIndex + j + 1, closingIndex);
+ MapSettable nextMap = new MapSettable();
+ readJwtObjectAsMap(nextMap, newJson);
+ values.put(name, nextMap.map);
+ i = closingIndex + 1;
+ } else if (json.charAt(sepIndex + j) == '[') {
+ int closingIndex = getClosingIndex(json, '[', ']', sepIndex + j);
+ String newJson = json.substring(sepIndex + j + 1, closingIndex);
+ values.put(name, readJwtObjectAsList(newJson));
+ i = closingIndex + 1;
+ } else {
+ int commaIndex = getCommaIndex(json, sepIndex + j);
+ Object value = readPrimitiveValue(json, sepIndex + j, commaIndex);
+ if (DATE_PROPERTIES.contains(name)) {
+ value = Long.valueOf(value.toString());
+ }
+ values.put(name, value);
+ i = commaIndex + 1;
+ }
+
+ }
+ }
+ protected List<Object> readJwtObjectAsList(String json) {
+ List<Object> values = new LinkedList<Object>();
+ for (int i = 0; i < json.length(); i++) {
+ if (isWhiteSpace(json.charAt(i))) {
+ continue;
+ }
+ if (json.charAt(i) == '{') {
+ int closingIndex = getClosingIndex(json, '{', '}', i);
+ MapSettable nextMap = new MapSettable();
+ readJwtObjectAsMap(nextMap, json.substring(i + 1, closingIndex));
+ values.add(nextMap.map);
+ i = closingIndex + 1;
+ } else {
+ int commaIndex = getCommaIndex(json, i);
+ Object value = readPrimitiveValue(json, i, commaIndex);
+ values.add(value);
+ i = commaIndex + 1;
+ }
+ }
+
+ return values;
+ }
+ protected Object readPrimitiveValue(String json, int from, int to) {
+ Object value = json.substring(from, to);
+ String valueStr = value.toString().trim();
+ if (valueStr.startsWith("\"")) {
+ value = valueStr.substring(1, valueStr.length() - 1);
+ } else if ("true".equals(value) || "false".equals(value)) {
+ value = Boolean.valueOf(valueStr);
+ }
+ return value;
+ }
+
+ protected static int getCommaIndex(String json, int from) {
+ int commaIndex = json.indexOf(",", from);
+ if (commaIndex == -1) {
+ commaIndex = json.length();
+ }
+ return commaIndex;
+ }
+ protected int getClosingIndex(String json, char openChar, char closeChar, int from) {
+ int nextOpenIndex = json.indexOf(openChar, from + 1);
+ int closingIndex = json.indexOf(closeChar, from + 1);
+ while (nextOpenIndex != -1 && nextOpenIndex < closingIndex) {
+ nextOpenIndex = json.indexOf(openChar, closingIndex + 1);
+ closingIndex = json.indexOf(closeChar, closingIndex + 1);
+ }
+ return closingIndex;
+ }
+ protected boolean isWhiteSpace(char jsonChar) {
+ return jsonChar == ' ' || jsonChar == '\r' || jsonChar == '\n' || jsonChar == '\t';
+ }
+
+ public void setFormat(boolean format) {
+ this.format = format;
+ }
+
+ private interface Settable {
+ void put(String key, Object value);
+ }
+ private static class MapSettable implements Settable {
+ private Map<String, Object> map = new LinkedHashMap<String, Object>();
+ public void put(String key, Object value) {
+ map.put(key, value);
+ }
+
+ }
+ private static class JoseObjectSettable implements Settable {
+ private AbstractJoseObject jose;
+ public JoseObjectSettable(AbstractJoseObject jose) {
+ this.jose = jose;
+ }
+ public void put(String key, Object value) {
+ jose.setValue(key, value);
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/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
new file mode 100644
index 0000000..a0b6a5b
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java
@@ -0,0 +1,81 @@
+/**
+ * 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;
+
+public final class JoseConstants {
+ public static final String HEADER_TYPE = "typ";
+ public static final String HEADER_ALGORITHM = "alg";
+ public static final String HEADER_CONTENT_TYPE = "cty";
+ public static final String HEADER_CRITICAL = "crit";
+
+ public static final String HEADER_KEY_ID = "kid";
+ public static final String HEADER_X509_URL = "x5u";
+ public static final String HEADER_X509_CHAIN = "x5c";
+ public static final String HEADER_X509_THUMBPRINT = "x5t";
+ public static final String HEADER_X509_THUMBPRINT_SHA256 = "x5t#S256";
+ public static final String HEADER_JSON_WEB_KEY = "jwk";
+ public static final String HEADER_JSON_WEB_KEY_SET = "jku";
+
+ public static final String JWE_HEADER_KEY_ENC_ALGORITHM = HEADER_ALGORITHM;
+ public static final String JWE_HEADER_CONTENT_ENC_ALGORITHM = "enc";
+ public static final String JWE_HEADER_ZIP_ALGORITHM = "zip";
+ public static final String DEFLATE_ZIP_ALGORITHM = "DEF";
+
+ 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_JSON = "application/jose+json";
+
+ public static final String PLAIN_TEXT_ALGO = "none";
+ public static final String HMAC_SHA_256_ALGO = "HS256";
+ public static final String HMAC_SHA_384_ALGO = "HS384";
+ public static final String HMAC_SHA_512_ALGO = "HS512";
+ public static final String RS_SHA_256_ALGO = "RS256";
+ public static final String RS_SHA_384_ALGO = "RS384";
+ public static final String RS_SHA_512_ALGO = "RS512";
+ public static final String ES_SHA_256_ALGO = "ES256";
+ public static final String ES_SHA_384_ALGO = "ES384";
+ public static final String ES_SHA_512_ALGO = "ES512";
+
+ // Key Encryption
+ public static final String RSA_OAEP_ALGO = "RSA-OAEP";
+ public static final String RSA_OAEP_256_ALGO = "RSA-OAEP-256";
+ public static final String RSA_1_5_ALGO = "RSA1_5";
+ public static final String A128KW_ALGO = "A128KW";
+ public static final String A192KW_ALGO = "A192KW";
+ public static final String A256KW_ALGO = "A256KW";
+ public static final String A128GCMKW_ALGO = "A128GCMKW";
+ public static final String A192GCMKW_ALGO = "A192GCMKW";
+ public static final String A256GCMKW_ALGO = "A256GCMKW";
+ public static final String PBES2_HS256_A128KW_ALGO = "PBES2-HS256+A128KW";
+ public static final String PBES2_HS384_A192KW_ALGO = "PBES2-HS384+A192KW";
+ public static final String PBES2_HS512_A256KW_ALGO = "PBES2-HS512+A256KW";
+ // Content Encryption
+ public static final String A128CBC_HS256_ALGO = "A128CBC-HS256";
+ public static final String A192CBC_HS384_ALGO = "A192CBC-HS384";
+ public static final String A256CBC_HS512_ALGO = "A256CBC-HS512";
+ public static final String A128GCM_ALGO = "A128GCM";
+ public static final String A192GCM_ALGO = "A192GCM";
+ public static final String A256GCM_ALGO = "A256GCM";
+
+ private JoseConstants() {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java
new file mode 100644
index 0000000..3577669
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java
@@ -0,0 +1,174 @@
+/**
+ * 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;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JoseHeaders extends AbstractJoseObject {
+ private Map<String, Integer> headerUpdateCount;
+ public JoseHeaders() {
+ }
+
+ public JoseHeaders(Map<String, Object> values) {
+ super(values);
+ }
+
+ public void setType(String type) {
+ setHeader(JoseConstants.HEADER_TYPE, type);
+ }
+
+ public String getType() {
+ return (String)getHeader(JoseConstants.HEADER_TYPE);
+ }
+
+ public void setContentType(String type) {
+ setHeader(JoseConstants.HEADER_CONTENT_TYPE, type);
+ }
+
+ public String getContentType() {
+ return (String)getHeader(JoseConstants.HEADER_CONTENT_TYPE);
+ }
+
+ public void setAlgorithm(String algo) {
+ setHeader(JoseConstants.HEADER_ALGORITHM, algo);
+ }
+
+ public String getAlgorithm() {
+ return (String)getHeader(JoseConstants.HEADER_ALGORITHM);
+ }
+
+ public void setKeyId(String kid) {
+ setHeader(JoseConstants.HEADER_KEY_ID, kid);
+ }
+
+ public String getKeyId() {
+ return (String)getHeader(JoseConstants.HEADER_KEY_ID);
+ }
+
+ public void setX509Url(String x509Url) {
+ setHeader(JoseConstants.HEADER_X509_URL, x509Url);
+ }
+
+ public String getX509Url() {
+ return (String)getHeader(JoseConstants.HEADER_X509_URL);
+ }
+
+ public void setX509Chain(String x509Chain) {
+ setHeader(JoseConstants.HEADER_X509_CHAIN, x509Chain);
+ }
+
+ public String getX509Chain() {
+ return (String)getHeader(JoseConstants.HEADER_X509_CHAIN);
+ }
+
+ public void setX509Thumbprint(String x509Thumbprint) {
+ setHeader(JoseConstants.HEADER_X509_THUMBPRINT, x509Thumbprint);
+ }
+
+ public String getX509Thumbprint() {
+ return (String)getHeader(JoseConstants.HEADER_X509_THUMBPRINT);
+ }
+
+ public void setX509ThumbprintSHA256(String x509Thumbprint) {
+ setHeader(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, x509Thumbprint);
+ }
+
+ public String getX509ThumbprintSHA256() {
+ return (String)super.getValue(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+ }
+
+ public void setCritical(List<String> crit) {
+ setHeader(JoseConstants.HEADER_CRITICAL, crit);
+ }
+
+ public List<String> getCritical() {
+ return CastUtils.cast((List<?>)getHeader(JoseConstants.HEADER_CRITICAL));
+ }
+
+ public void setJsonWebKey(JsonWebKey key) {
+ setHeader(JoseConstants.HEADER_JSON_WEB_KEY, key);
+ }
+
+ public JsonWebKey getJsonWebKey() {
+ Object jsonWebKey = getValue(JoseConstants.HEADER_JSON_WEB_KEY);
+ if (jsonWebKey == null || jsonWebKey instanceof JsonWebKey) {
+ return (JsonWebKey)jsonWebKey;
+ }
+ Map<String, Object> map = CastUtils.cast((Map<?, ?>)jsonWebKey);
+ return new JsonWebKey(map);
+ }
+
+ public JoseHeaders setHeader(String name, Object value) {
+ setValue(name, value);
+ return this;
+ }
+
+ protected void setValue(String name, Object value) {
+ if (super.values.containsKey(name)) {
+ if (headerUpdateCount == null) {
+ headerUpdateCount = new LinkedHashMap<String, Integer>();
+ }
+ Integer count = headerUpdateCount.get(name);
+ count = count == null ? 2 : count++;
+ headerUpdateCount.put(name, count);
+ }
+ super.setValue(name, value);
+ }
+
+ public Object getHeader(String name) {
+ return getValue(name);
+ }
+
+ public JoseHeaders setIntegerHeader(String name, Integer value) {
+ setHeader(name, value);
+ return this;
+ }
+
+ public Integer getIntegerHeader(String name) {
+ Object value = getHeader(name);
+ if (value != null) {
+ return value instanceof Integer ? (Integer)value : Integer.parseInt(value.toString());
+ } else {
+ return null;
+ }
+ }
+ public JoseHeaders setLongHeader(String name, Long value) {
+ setHeader(name, value);
+ return this;
+ }
+
+ public Long getLongHeader(String name) {
+ Object value = getHeader(name);
+ if (value != null) {
+ return value instanceof Long ? (Long)value : Long.parseLong(value.toString());
+ } else {
+ return null;
+ }
+ }
+ public Map<String, Object> getHeaderUpdateCount() {
+ return headerUpdateCount == null ? null : Collections.<String, Object>unmodifiableMap(headerUpdateCount);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReader.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReader.java
new file mode 100644
index 0000000..a99ca23
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReader.java
@@ -0,0 +1,24 @@
+/**
+ * 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;
+
+
+public interface JoseHeadersReader {
+ JoseHeaders fromJsonHeaders(String jsonHeaders);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReaderWriter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReaderWriter.java
new file mode 100644
index 0000000..be20ca3
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersReaderWriter.java
@@ -0,0 +1,39 @@
+/**
+ * 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;
+
+
+
+
+
+public class JoseHeadersReaderWriter extends AbstractJoseObjectReaderWriter
+ implements JoseHeadersReader, JoseHeadersWriter {
+ @Override
+ public String headersToJson(JoseHeaders headers) {
+ return toJson(headers);
+ }
+
+ @Override
+ public JoseHeaders fromJsonHeaders(String headersJson) {
+ JoseHeaders headers = new JoseHeaders();
+ fromJsonInternal(headers, headersJson);
+ return headers;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersWriter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersWriter.java
new file mode 100644
index 0000000..54a77e7
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeadersWriter.java
@@ -0,0 +1,25 @@
+/**
+ * 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;
+
+public interface JoseHeadersWriter {
+
+ String headersToJson(JoseHeaders headers);
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
new file mode 100644
index 0000000..9abbe79
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
@@ -0,0 +1,46 @@
+/**
+ * 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;
+
+public final class JoseUtils {
+ private JoseUtils() {
+
+ }
+
+ public static String checkContentType(String contentType, String defaultType) {
+ if (contentType != null) {
+ int paramIndex = contentType.indexOf(';');
+ String typeWithoutParams = paramIndex == -1 ? contentType : contentType.substring(0, paramIndex);
+ if (typeWithoutParams.indexOf('/') == -1) {
+ contentType = "application/" + contentType;
+ }
+ } else {
+ contentType = defaultType;
+ }
+ return contentType;
+ }
+ public static String expandContentType(String contentType) {
+ int paramIndex = contentType.indexOf(';');
+ String typeWithoutParams = paramIndex == -1 ? contentType : contentType.substring(0, paramIndex);
+ if (typeWithoutParams.indexOf('/') == -1) {
+ contentType = "application/" + contentType;
+ }
+ return contentType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/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
new file mode 100644
index 0000000..a1bd5cf
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java
@@ -0,0 +1,134 @@
+/**
+ * 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.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 {
+ JweDecryptionProvider theDecryptor = getInitializedDecryptionProvider();
+ JweDecryptionOutput out = theDecryptor.decrypt(new String(IOUtils.readBytesFromStream(is), "UTF-8"));
+ validateHeaders(out.getHeaders());
+ return out;
+ }
+
+ protected void validateHeaders(JweHeaders headers) {
+ // complete
+ }
+ public void setDecryptionProvider(JweDecryptionProvider decryptor) {
+ this.decryption = decryptor;
+ }
+ protected JweDecryptionProvider getInitializedDecryptionProvider() {
+ if (decryption != null) {
+ return decryption;
+ }
+ Message m = JAXRSUtils.getCurrentMessage();
+ String propLoc =
+ (String)MessageUtils.getContextualProperty(m, RSSEC_ENCRYPTION_IN_PROPS, RSSEC_ENCRYPTION_PROPS);
+ 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;
+ }
+ public String getDefaultMediaType() {
+ return defaultMediaType;
+ }
+
+ public void setDefaultMediaType(String defaultMediaType) {
+ this.defaultMediaType = defaultMediaType;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/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
new file mode 100644
index 0000000..6902e97
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java
@@ -0,0 +1,92 @@
+/**
+ * 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.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;
+
+ public void setSignatureVerifier(JwsSignatureVerifier signatureVerifier) {
+ this.sigVerifier = signatureVerifier;
+ }
+
+ protected JwsSignatureVerifier getInitializedSigVerifier() {
+ if (sigVerifier != null) {
+ return sigVerifier;
+ }
+
+ Message m = JAXRSUtils.getCurrentMessage();
+ String propLoc =
+ (String)MessageUtils.getContextualProperty(m, RSSEC_SIGNATURE_IN_PROPS, RSSEC_SIGNATURE_PROPS);
+ 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);
+ }
+ }
+
+ public String getDefaultMediaType() {
+ return defaultMediaType;
+ }
+
+ public void setDefaultMediaType(String defaultMediaType) {
+ 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/9c053334/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
new file mode 100644
index 0000000..480f83d
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
@@ -0,0 +1,94 @@
+/**
+ * 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.security.interfaces.RSAPrivateKey;
+import java.util.Properties;
+
+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.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;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+
+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;
+
+ public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
+ this.sigProvider = signatureProvider;
+ }
+
+ protected JwsSignatureProvider getInitializedSigProvider(JwtHeaders headers) {
+ if (sigProvider != null) {
+ return sigProvider;
+ }
+ Message m = JAXRSUtils.getCurrentMessage();
+ String propLoc =
+ (String)MessageUtils.getContextualProperty(m, RSSEC_SIGNATURE_OUT_PROPS, RSSEC_SIGNATURE_PROPS);
+ 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);
+ }
+ }
+ protected void writeJws(JwsCompactProducer p, JwsSignatureProvider theSigProvider, OutputStream os)
+ throws IOException {
+ p.signWith(theSigProvider);
+ IOUtils.copy(new ByteArrayInputStream(p.getSignedEncodedJws().getBytes("UTF-8")), 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/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweClientResponseFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweClientResponseFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweClientResponseFilter.java
new file mode 100644
index 0000000..d04d4c2
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweClientResponseFilter.java
@@ -0,0 +1,46 @@
+/**
+ * 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 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.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionOutput;
+
+@Priority(Priorities.JWE_CLIENT_READ_PRIORITY)
+public class JweClientResponseFilter extends AbstractJweDecryptingFilter implements ClientResponseFilter {
+ @Override
+ public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException {
+ JweDecryptionOutput out = decrypt(res.getEntityStream());
+ byte[] bytes = out.getContent();
+ res.setEntityStream(new ByteArrayInputStream(bytes));
+ res.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length));
+ String ct = JoseUtils.checkContentType(out.getHeaders().getContentType(), getDefaultMediaType());
+ if (ct != null) {
+ res.getHeaders().putSingle("Content-Type", ct);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweContainerRequestFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweContainerRequestFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweContainerRequestFilter.java
new file mode 100644
index 0000000..c58fe7e
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweContainerRequestFilter.java
@@ -0,0 +1,46 @@
+/**
+ * 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 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.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionOutput;
+
+@PreMatching
+@Priority(Priorities.JWE_SERVER_READ_PRIORITY)
+public class JweContainerRequestFilter extends AbstractJweDecryptingFilter implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext context) throws IOException {
+ JweDecryptionOutput out = decrypt(context.getEntityStream());
+ byte[] bytes = out.getContent();
+ context.setEntityStream(new ByteArrayInputStream(bytes));
+ context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length));
+ String ct = JoseUtils.checkContentType(out.getHeaders().getContentType(), getDefaultMediaType());
+ if (ct != null) {
+ context.getHeaders().putSingle("Content-Type", ct);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/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
new file mode 100644
index 0000000..d35c519
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java
@@ -0,0 +1,200 @@
+/**
+ * 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.security.interfaces.RSAPublicKey;
+import java.util.Properties;
+import java.util.zip.DeflaterOutputStream;
+
+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.Bus;
+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;
+ private JoseHeadersWriter writer = new JoseHeadersReaderWriter();
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException {
+
+ OutputStream actualOs = ctx.getOutputStream();
+
+ JweEncryptionProvider theEncryptionProvider = getInitializedEncryptionProvider();
+
+ String ctString = null;
+ if (contentTypeRequired) {
+ MediaType mt = ctx.getMediaType();
+ if (mt != null) {
+ if ("application".equals(mt.getType())) {
+ ctString = mt.getSubtype();
+ } else {
+ ctString = JAXRSUtils.mediaTypeToString(mt);
+ }
+ }
+ }
+
+ ctx.setMediaType(JAXRSUtils.toMediaType(JoseConstants.MEDIA_TYPE_JOSE_JSON));
+ if (useJweOutputStream) {
+ JweEncryptionState encryption = theEncryptionProvider.createJweEncryptionState(ctString);
+ try {
+ JweCompactProducer.startJweContent(actualOs,
+ encryption.getHeaders(),
+ writer,
+ encryption.getContentEncryptionKey(),
+ encryption.getIv());
+ } catch (IOException ex) {
+ throw new SecurityException(ex);
+ }
+ OutputStream jweStream = new JweOutputStream(actualOs, encryption.getCipher(),
+ encryption.getAuthTagProducer());
+ if (encryption.isCompressionSupported()) {
+ jweStream = new DeflaterOutputStream(jweStream);
+ }
+
+ ctx.setOutputStream(jweStream);
+ ctx.proceed();
+ jweStream.flush();
+ } else {
+ CachedOutputStream cos = new CachedOutputStream();
+ ctx.setOutputStream(cos);
+ ctx.proceed();
+ String jweContent = theEncryptionProvider.encrypt(cos.getBytes(), ctString);
+ IOUtils.copy(new ByteArrayInputStream(jweContent.getBytes("UTF-8")), actualOs);
+ actualOs.flush();
+ }
+ }
+
+ protected JweEncryptionProvider getInitializedEncryptionProvider() {
+ if (encryptionProvider != null) {
+ return encryptionProvider;
+ }
+ Message m = JAXRSUtils.getCurrentMessage();
+ String propLoc =
+ (String)MessageUtils.getContextualProperty(m, RSSEC_ENCRYPTION_OUT_PROPS, RSSEC_ENCRYPTION_PROPS);
+ 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;
+ }
+ public void setUseJweOutputStream(boolean useJweOutputStream) {
+ this.useJweOutputStream = useJweOutputStream;
+ }
+
+ public void setWriter(JoseHeadersWriter writer) {
+ this.writer = writer;
+ }
+
+ public void setEncryptionProvider(JweEncryptionProvider encryptionProvider) {
+ this.encryptionProvider = encryptionProvider;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
new file mode 100644
index 0000000..64a1cfa
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
@@ -0,0 +1,52 @@
+/**
+ * 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 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.JwsCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+
+@Priority(Priorities.JWS_CLIENT_READ_PRIORITY)
+public class JwsClientResponseFilter extends AbstractJwsReaderProvider implements ClientResponseFilter {
+ @Override
+ public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException {
+ JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+ JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(res.getEntityStream()));
+ if (!p.verifySignatureWith(theSigVerifier)) {
+ throw new SecurityException();
+ }
+ byte[] bytes = p.getDecodedJwsPayloadBytes();
+ res.setEntityStream(new ByteArrayInputStream(bytes));
+ res.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length));
+ String ct = JoseUtils.checkContentType(p.getJwsHeaders().getContentType(), getDefaultMediaType());
+ if (ct != null) {
+ res.getHeaders().putSingle("Content-Type", ct);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
new file mode 100644
index 0000000..fbd051d
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
@@ -0,0 +1,56 @@
+/**
+ * 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 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.JwsCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+
+@PreMatching
+@Priority(Priorities.JWS_SERVER_READ_PRIORITY)
+public class JwsContainerRequestFilter extends AbstractJwsReaderProvider implements ContainerRequestFilter {
+ @Override
+ public void filter(ContainerRequestContext context) throws IOException {
+
+ JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+ JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(context.getEntityStream()));
+ if (!p.verifySignatureWith(theSigVerifier)) {
+ context.abortWith(JAXRSUtils.toResponse(400));
+ return;
+ }
+ byte[] bytes = p.getDecodedJwsPayloadBytes();
+ context.setEntityStream(new ByteArrayInputStream(bytes));
+ context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length));
+
+ String ct = JoseUtils.checkContentType(p.getJwsHeaders().getContentType(), getDefaultMediaType());
+ if (ct != null) {
+ context.getHeaders().putSingle("Content-Type", ct);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJwtMessageBodyReader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJwtMessageBodyReader.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJwtMessageBodyReader.java
new file mode 100644
index 0000000..b1c1f53
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsJwtMessageBodyReader.java
@@ -0,0 +1,54 @@
+/**
+ * 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.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+
+public class JwsJwtMessageBodyReader extends AbstractJwsReaderProvider
+ implements MessageBodyReader<JwtToken> {
+
+ @Override
+ public boolean isReadable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) {
+ return cls == JwtToken.class;
+ }
+
+ @Override
+ public JwtToken readFrom(Class<JwtToken> cls, Type t, Annotation[] anns, MediaType mt,
+ MultivaluedMap<String, String> headers, InputStream is) throws IOException,
+ WebApplicationException {
+ JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+ JwsJwtCompactConsumer p = new JwsJwtCompactConsumer(IOUtils.readStringFromStream(is));
+ p.verifySignatureWith(theSigVerifier);
+ return p.getJwtToken();
+ }
+
+}