cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [13/20] cxf git commit: Splitting current jose module into jose-core + jose-jaxrs
Date Tue, 13 Oct 2015 10:42:13 GMT
http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonOutputStream.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonOutputStream.java
new file mode 100644
index 0000000..7fe6059
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonOutputStream.java
@@ -0,0 +1,100 @@
+/**
+ * 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.jws;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+
+public class JwsJsonOutputStream extends FilterOutputStream {
+    private boolean flushed;
+    private List<String> protectedHeaders;
+    private List<JwsSignature> signatures;
+    private ExecutorService executor;
+    public JwsJsonOutputStream(OutputStream out, 
+                               List<String> protectedHeaders,
+                               List<JwsSignature> signatures) {
+        super(out);
+        this.protectedHeaders = protectedHeaders;
+        this.signatures = signatures;
+        // This can be further optimized by having a dedicated thread per signature,
+        // can make a difference if a number of signatures to be created is > 2
+        this.executor = Executors.newSingleThreadExecutor();
+    }
+
+    @Override
+    public void write(int value) throws IOException {
+        byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 8).putInt(value).array();
+        write(bytes, 0, bytes.length);
+    }
+    
+    @Override
+    public void write(final byte b[], final int off, final int len) throws IOException {
+        //TODO: Review if it is at least theoretically possible that a given b[] region
+        // can be modified in a subsequent write which might affect the signature calculation  
+        executor.execute(new Runnable() {
+            public void run() {
+                for (JwsSignature signature : signatures) {
+                    signature.update(b, off, len);
+                }
+            }
+        });
+        out.write(b, off, len);
+        out.flush();
+    }
+    @Override
+    public void flush() throws IOException {
+        if (flushed) {
+            return;
+        }
+        out.write(StringUtils.toBytesUTF8("\",\"signatures\":["));
+        shutdownExecutor();
+        for (int i = 0; i < signatures.size(); i++) {
+            if (i > 0) {
+                out.write(new byte[]{','});
+            }
+            out.write(StringUtils.toBytesUTF8("{\"protected\":\"" 
+                                             + protectedHeaders.get(i) 
+                                             + "\",\"signature\":\""));
+            byte[] sign = signatures.get(i).sign();
+            Base64UrlUtility.encodeAndStream(sign, 0, sign.length, out);
+            out.write(StringUtils.toBytesUTF8("\"}"));
+        }
+        out.write(StringUtils.toBytesUTF8("]}"));
+        flushed = true;
+    }
+    private void shutdownExecutor() {
+        executor.shutdown();
+        while (!executor.isTerminated()) {
+            try {
+                executor.awaitTermination(1, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
new file mode 100644
index 0000000..712b2c0
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
@@ -0,0 +1,212 @@
+/**
+ * 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.jws;
+
+import java.security.PrivateKey;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JwsJsonProducer {
+    protected static final Logger LOG = LogUtils.getL7dLogger(JwsJsonProducer.class);
+    private boolean supportFlattened;
+    private String plainPayload;
+    private String encodedPayload;
+    private List<JwsJsonSignatureEntry> signatures = new LinkedList<JwsJsonSignatureEntry>();
+    private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter();
+    public JwsJsonProducer(String tbsDocument) {
+        this(tbsDocument, false);
+    }
+    public JwsJsonProducer(String tbsDocument, boolean supportFlattened) {
+        this.supportFlattened = supportFlattened;
+        this.plainPayload = tbsDocument;
+    }
+    
+    public String getPlainPayload() {
+        return plainPayload;
+    }
+    public String getUnsignedEncodedPayload() {
+        if (encodedPayload == null) { 
+            encodedPayload = Base64UrlUtility.encode(getPlainPayload());
+        }
+        return encodedPayload;
+    }
+    public String getJwsJsonSignedDocument() {
+        return getJwsJsonSignedDocument(false);
+    }
+    public String getJwsJsonSignedDocument(boolean detached) {
+        if (signatures.isEmpty()) { 
+            return null;
+        }
+        
+        Boolean b64Status = validateB64Status(signatures);
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        if (!detached) {
+            sb.append("\"payload\":\"" + getActualPayload(b64Status) + "\"");
+            sb.append(",");
+        }
+        if (!supportFlattened || signatures.size() > 1) {
+            sb.append("\"signatures\":[");
+            for (int i = 0; i < signatures.size(); i++) {
+                JwsJsonSignatureEntry signature = signatures.get(i);
+                if (i > 0) {
+                    sb.append(",");
+                }
+                sb.append(signature.toJson());
+            }
+            sb.append("]");
+        } else {
+            sb.append(signatures.get(0).toJson(true));
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+    public List<JwsJsonSignatureEntry> getSignatureEntries() {
+        return signatures;
+    }
+    
+    /*
+     * TODO
+    public MultivaluedMap<SignatureAlgorithm, 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) {
+        JwsHeaders headers = new JwsHeaders();
+        headers.setSignatureAlgorithm(signer.getAlgorithm());
+        return signWith(signer, headers);
+    }
+    public String signWith(JwsSignatureProvider signer, 
+                           JwsHeaders protectedHeader) {
+        return signWith(signer, protectedHeader, null);
+    }
+    public String signWith(JsonWebKey jwk) {
+        return signWith(JwsUtils.getSignatureProvider(jwk));
+    }
+    public String signWith(PrivateKey key, SignatureAlgorithm algo) {
+        return signWith(JwsUtils.getPrivateKeySignatureProvider(key, algo));
+    }
+    public String signWith(byte[] key, SignatureAlgorithm algo) {
+        return signWith(JwsUtils.getHmacSignatureProvider(key, algo));
+    }
+    public String signWith(JwsSignatureProvider signer,
+                           JwsHeaders protectedHeader,
+                           JwsHeaders unprotectedHeader) {
+        JwsHeaders unionHeaders = new JwsHeaders();
+         
+        if (protectedHeader != null) {
+            unionHeaders.asMap().putAll(protectedHeader.asMap());
+        }
+        if (unprotectedHeader != null) {
+            checkUnprotectedHeaders(unprotectedHeader, 
+                                    JoseConstants.HEADER_CRITICAL,
+                                    JoseConstants.JWS_HEADER_B64_STATUS_HEADER);
+            if (!Collections.disjoint(unionHeaders.asMap().keySet(), 
+                                     unprotectedHeader.asMap().keySet())) {
+                LOG.warning("Protected and unprotected headers have duplicate values");
+                throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+            }
+            unionHeaders.asMap().putAll(unprotectedHeader.asMap());
+        }
+        if (unionHeaders.getSignatureAlgorithm() == null) {
+            LOG.warning("Algorithm header is not set");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        String sequenceToBeSigned;
+        String actualPayload = protectedHeader != null 
+            ? getActualPayload(protectedHeader.getPayloadEncodingStatus()) 
+            : getUnsignedEncodedPayload();
+        if (protectedHeader != null) {
+            sequenceToBeSigned = Base64UrlUtility.encode(writer.toJson(protectedHeader))
+                    + "." + actualPayload;
+        } else {
+            sequenceToBeSigned = "." + getUnsignedEncodedPayload();
+        }
+        byte[] bytesToBeSigned = StringUtils.toBytesUTF8(sequenceToBeSigned);
+        
+        byte[] signatureBytes = signer.sign(unionHeaders, bytesToBeSigned);
+        
+        String encodedSignatureBytes = Base64UrlUtility.encode(signatureBytes);
+        JwsJsonSignatureEntry signature;
+        if (protectedHeader != null) {
+            signature = new JwsJsonSignatureEntry(actualPayload,
+                    Base64UrlUtility.encode(writer.toJson(protectedHeader)),
+                    encodedSignatureBytes,
+                    unprotectedHeader);
+        } else {
+            signature = new JwsJsonSignatureEntry(getUnsignedEncodedPayload(),
+                    null,
+                    encodedSignatureBytes,
+                    unprotectedHeader);
+        }
+        return updateJwsJsonSignedDocument(signature);
+    }
+    private String getActualPayload(Boolean payloadEncodingStatus) {
+        return Boolean.FALSE == payloadEncodingStatus 
+            ? getPlainPayload() : this.getUnsignedEncodedPayload();
+    }
+    private String updateJwsJsonSignedDocument(JwsJsonSignatureEntry signature) {
+        signatures.add(signature);
+        return getJwsJsonSignedDocument();
+    }
+    private static void checkUnprotectedHeaders(JoseHeaders unprotected, String... headerNames) {
+        for (String headerName : headerNames) {
+            if (unprotected.containsHeader(headerName)) {
+                LOG.warning("Unprotected headers contain a header \"" 
+                    + headerName + "\" which must be protected");
+                throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+            }
+        }
+    }
+    static Boolean validateB64Status(List<JwsJsonSignatureEntry> signatures) {
+        Set<Boolean> b64Set = new LinkedHashSet<Boolean>();
+        for (JwsJsonSignatureEntry entry : signatures) {
+            JwsHeaders headers = entry.getProtectedHeader();
+            Boolean status = headers != null ? headers.getPayloadEncodingStatus() : null;
+            if (status == null) {
+                status = Boolean.TRUE;
+            }
+            b64Set.add(status);
+        }
+        if (b64Set.size() > 1) {
+            LOG.warning("Each signature entry can sign only encoded or only unencoded payload");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        return b64Set.iterator().next();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
new file mode 100644
index 0000000..dd2e590
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
@@ -0,0 +1,163 @@
+/**
+ * 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.jws;
+
+import java.util.Collections;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+
+public class JwsJsonSignatureEntry {
+    protected static final Logger LOG = LogUtils.getL7dLogger(JwsJsonSignatureEntry.class);
+    private String jwsPayload;
+    private String encodedProtectedHeader;
+    private String encodedSignature;
+    private JwsHeaders protectedHeader;
+    private JwsHeaders unprotectedHeader;
+    private JwsHeaders unionHeaders;
+    private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter();
+      
+    public JwsJsonSignatureEntry(String jwsPayload,
+                                 String encodedProtectedHeader,
+                                 String encodedSignature,
+                                 JwsHeaders unprotectedHeader) {
+        if (encodedProtectedHeader == null && unprotectedHeader == null || encodedSignature == null) {
+            LOG.warning("Invalid Signature entry");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        
+        this.jwsPayload = jwsPayload;
+        this.encodedProtectedHeader = encodedProtectedHeader;
+        this.encodedSignature = encodedSignature;
+        this.unprotectedHeader = unprotectedHeader;
+        if (encodedProtectedHeader != null) {
+            this.protectedHeader = new JwsHeaders(writer.fromJson(JoseUtils.decodeToString(encodedProtectedHeader)));
+        }
+        prepare();
+    }
+    private void prepare() {
+        unionHeaders = new JwsHeaders();
+        
+        if (protectedHeader != null) {
+            unionHeaders.asMap().putAll(protectedHeader.asMap());
+        }
+        if (unprotectedHeader != null) {
+            if (!Collections.disjoint(unionHeaders.asMap().keySet(), 
+                                     unprotectedHeader.asMap().keySet())) {
+                LOG.warning("Protected and unprotected headers have duplicate values");
+                throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+            }
+            unionHeaders.asMap().putAll(unprotectedHeader.asMap());
+        }
+    }
+    public String getJwsPayload() {
+        return jwsPayload;
+    }
+    public String getDecodedJwsPayload() {
+        if (protectedHeader == null || !JwsUtils.isPayloadUnencoded(protectedHeader)) {
+            return JoseUtils.decodeToString(jwsPayload);
+        } else {
+            return jwsPayload;
+        }
+    }
+    public byte[] getDecodedJwsPayloadBytes() {
+        return StringUtils.toBytesUTF8(getDecodedJwsPayload());
+    }
+    public String getEncodedProtectedHeader() {
+        return encodedProtectedHeader;
+    }
+    public JwsHeaders getProtectedHeader() {
+        return protectedHeader;
+    }
+    public JwsHeaders getUnprotectedHeader() {
+        return unprotectedHeader;
+    }
+    public JwsHeaders getUnionHeader() {
+        return unionHeaders;
+    }
+    public String getEncodedSignature() {
+        return encodedSignature;
+    }
+    public byte[] getDecodedSignature() {
+        return JoseUtils.decode(getEncodedSignature());
+    }
+    public String getUnsignedSequence() {
+        if (getEncodedProtectedHeader() != null) {
+            return getEncodedProtectedHeader() + "." + getJwsPayload();
+        } else {
+            return "." + getJwsPayload();
+        }
+    }
+    public String getKeyId() {
+        return getUnionHeader().getKeyId();
+    }
+    public boolean verifySignatureWith(JwsSignatureVerifier validator) {
+        try {
+            if (validator.verify(getUnionHeader(),
+                                 getUnsignedSequence(),
+                                 getDecodedSignature())) {
+                return true;
+            }
+        } catch (JwsException ex) {
+            // ignore
+        }
+        LOG.warning("Invalid Signature Entry");
+        return false;
+    }
+    public boolean verifySignatureWith(JsonWebKey key) {
+        return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
+    }
+    public boolean validateCriticalHeaders() {
+        if (this.getUnprotectedHeader().getHeader(JoseConstants.HEADER_CRITICAL) != null) {
+            return false;
+        }
+        return JwsUtils.validateCriticalHeaders(getUnionHeader());
+    }
+    public String toJson() {
+        return toJson(false);
+    }
+    public String toJson(boolean flattenedMode) {
+        StringBuilder sb = new StringBuilder();
+        if (!flattenedMode) {
+            sb.append("{");
+        }
+        if (protectedHeader != null) {
+            sb.append("\"protected\":\"" + Base64UrlUtility.encode(writer.toJson(protectedHeader)) + "\"");
+        }
+        if (unprotectedHeader != null) {
+            if (protectedHeader != null) {
+                sb.append(",");
+            }
+            sb.append("\"header\":" + writer.toJson(unprotectedHeader));
+        }
+        sb.append(",");
+        sb.append("\"signature\":\"" + encodedSignature + "\"");
+        if (!flattenedMode) {
+            sb.append("}");
+        }
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java
new file mode 100644
index 0000000..e2bcfa8
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java
@@ -0,0 +1,43 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+
+public class JwsJwtCompactConsumer extends JwsCompactConsumer {
+    private JwtToken token;
+    public JwsJwtCompactConsumer(String encodedJws) {
+        super(encodedJws, null, new JwtTokenReaderWriter());
+    }
+    public JwtClaims getJwtClaims() {
+        return getJwtToken().getClaims();
+    }
+    public JwtToken getJwtToken() {
+        if (token == null) {
+            JwsHeaders theHeaders = super.getJwsHeaders();
+            JwtClaims theClaims = 
+                ((JwtTokenReaderWriter)getReader()).fromJsonClaims(getDecodedJwsPayload());
+            token = new JwtToken(theHeaders, theClaims);
+        }
+        return token;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
new file mode 100644
index 0000000..aaaa004
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
@@ -0,0 +1,44 @@
+/**
+ * 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.jws;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.jose.jwt.JwtUtils;
+
+
+public class JwsJwtCompactProducer extends JwsCompactProducer {
+    
+    public JwsJwtCompactProducer(JwtToken token) {
+        this(token, null);
+    }
+    public JwsJwtCompactProducer(JwtClaims claims) {
+        this(new JwtToken(null, claims), null);
+    }
+    public JwsJwtCompactProducer(JoseHeaders headers, JwtClaims claims) {
+        this(new JwtToken(headers, claims), null);
+    }
+    protected JwsJwtCompactProducer(JwtToken token, JwtTokenReaderWriter w) {
+        super(new JwsHeaders(token.getHeaders()), w, 
+              JwtUtils.claimsToJson(token.getClaims(), w));
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
new file mode 100644
index 0000000..53b592f
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
@@ -0,0 +1,59 @@
+/**
+ * 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.jws;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.cxf.common.util.Base64UrlUtility;
+
+public class JwsOutputStream extends FilterOutputStream {
+    private boolean flushed;
+    private JwsSignature signature;
+    public JwsOutputStream(OutputStream out, JwsSignature signature) {
+        super(out);
+        this.signature = signature;
+    }
+
+    @Override
+    public void write(int value) throws IOException {
+        byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 8).putInt(value).array();
+        write(bytes, 0, bytes.length);
+    }
+    
+    @Override
+    public void write(byte b[], int off, int len) throws IOException {
+        signature.update(b, off, len);
+        out.write(b, off, len);
+        out.flush();
+    }
+    @Override
+    public void flush() throws IOException {
+        if (flushed) {
+            return;
+        }
+        byte[] finalBytes = signature.sign();
+        out.write(new byte[]{'.'});
+        Base64UrlUtility.encodeAndStream(finalBytes, 0, finalBytes.length, out);
+        flushed = true;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.java
new file mode 100644
index 0000000..778b5cb
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.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.jws;
+
+
+public interface JwsSignature {
+    void update(byte[] src, int off, int len);
+    byte[] sign();
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java
new file mode 100644
index 0000000..00f0c2a
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java
@@ -0,0 +1,31 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+
+public interface JwsSignatureProvider {
+    SignatureAlgorithm getAlgorithm();
+    byte[] sign(JwsHeaders headers, byte[] content);
+    /**
+     * Create a signature handler capable of updating the signature input (optional operation)
+     */
+    JwsSignature createJwsSignature(JwsHeaders headers);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java
new file mode 100644
index 0000000..c44a678
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java
@@ -0,0 +1,26 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public interface JwsSignatureVerifier {
+    SignatureAlgorithm getAlgorithm();
+    boolean verify(JwsHeaders headers, String unsignedText, byte[] signature);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
new file mode 100644
index 0000000..abe1f27
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
@@ -0,0 +1,401 @@
+/**
+ * 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.jws;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.common.KeyManagementUtils;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+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.jwk.KeyOperation;
+import org.apache.cxf.rs.security.jose.jwk.KeyType;
+
+public final class JwsUtils {
+    private static final Logger LOG = LogUtils.getL7dLogger(JwsUtils.class);
+    private static final String JSON_WEB_SIGNATURE_ALGO_PROP = "rs.security.jws.content.signature.algorithm";
+    private static final String RSSEC_SIGNATURE_OUT_PROPS = "rs.security.signature.out.properties";
+    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 RSSEC_REPORT_KEY_PROP = "rs.security.jws.report.public.key";
+    private static final String RSSEC_REPORT_KEY_ID_PROP = "rs.security.jws.report.public.key.id";
+    private JwsUtils() {
+        
+    }
+    public static String sign(PrivateKey key, SignatureAlgorithm algo, String content) {
+        return sign(key, algo, content, null);
+    }
+    
+    
+    public static String sign(PrivateKey key, SignatureAlgorithm algo, String content, String ct) {
+        return sign(getPrivateKeySignatureProvider(key, algo), content, ct);
+    }
+    public static String sign(byte[] key, SignatureAlgorithm algo, String content) {
+        return sign(key, algo, content, null);
+    }
+    public static String sign(byte[] key, SignatureAlgorithm algo, String content, String ct) {
+        return sign(getHmacSignatureProvider(key, algo), content, ct);
+    }
+    public static String verify(PublicKey key, SignatureAlgorithm algo, String content) {
+        JwsCompactConsumer jws = verify(getPublicKeySignatureVerifier(key, algo), content);
+        return jws.getDecodedJwsPayload();
+    }
+    public static String verify(byte[] key, SignatureAlgorithm algo, String content) {
+        JwsCompactConsumer jws = verify(getHmacSignatureVerifier(key, algo), content);
+        return jws.getDecodedJwsPayload();
+    }
+    public static JwsSignatureProvider getSignatureProvider(JsonWebKey jwk) {
+        return getSignatureProvider(jwk, null);
+    }
+    public static JwsSignatureProvider getSignatureProvider(JsonWebKey jwk, 
+                                                            SignatureAlgorithm defaultAlgorithm) {
+        SignatureAlgorithm sigAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm 
+            : SignatureAlgorithm.getAlgorithm(jwk.getAlgorithm());
+        JwsSignatureProvider theSigProvider = null;
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.RSA == keyType) {
+            theSigProvider = getPrivateKeySignatureProvider(JwkUtils.toRSAPrivateKey(jwk),
+                                                            sigAlgo);
+        } else if (KeyType.OCTET == keyType) { 
+            byte[] key = JoseUtils.decode((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE));
+            theSigProvider = getHmacSignatureProvider(key, sigAlgo);
+        } else if (KeyType.EC == jwk.getKeyType()) {
+            theSigProvider = getPrivateKeySignatureProvider(JwkUtils.toECPrivateKey(jwk),
+                                                            sigAlgo);
+        }
+        return theSigProvider;
+    }
+    public static JwsSignatureProvider getPrivateKeySignatureProvider(PrivateKey key, SignatureAlgorithm algo) {
+        if (algo == null) {
+            LOG.warning("No signature algorithm was defined");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        if (key instanceof ECPrivateKey) {
+            return new EcDsaJwsSignatureProvider((ECPrivateKey)key, algo);
+        } else if (key instanceof RSAPrivateKey) {
+            return new PrivateKeyJwsSignatureProvider(key, algo);
+        }
+        
+        return null;
+    }
+    public static JwsSignatureProvider getHmacSignatureProvider(byte[] key, SignatureAlgorithm algo) {
+        if (algo == null) {
+            LOG.warning("No signature algorithm was defined");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        if (AlgorithmUtils.isHmacSign(algo.getJwaName())) {
+            return new HmacJwsSignatureProvider(key, algo);
+        }
+        return null;
+    }
+    public static JwsSignatureVerifier getSignatureVerifier(JsonWebKey jwk) {
+        return getSignatureVerifier(jwk, null);
+    }
+    public static JwsSignatureVerifier getSignatureVerifier(JsonWebKey jwk, SignatureAlgorithm defaultAlgorithm) {
+        SignatureAlgorithm sigAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm 
+            : SignatureAlgorithm.getAlgorithm(jwk.getAlgorithm());
+        JwsSignatureVerifier theVerifier = null;
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.RSA == keyType) {
+            theVerifier = getPublicKeySignatureVerifier(JwkUtils.toRSAPublicKey(jwk, true), sigAlgo);
+        } else if (KeyType.OCTET == keyType) { 
+            byte[] key = JoseUtils.decode((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE));
+            theVerifier = getHmacSignatureVerifier(key, sigAlgo);
+        } else if (KeyType.EC == keyType) {
+            theVerifier = getPublicKeySignatureVerifier(JwkUtils.toECPublicKey(jwk), sigAlgo);
+        }
+        return theVerifier;
+    }
+    public static JwsSignatureVerifier getPublicKeySignatureVerifier(X509Certificate cert, SignatureAlgorithm algo) {
+        return getPublicKeySignatureVerifier(cert.getPublicKey(), algo);
+    }
+    public static JwsSignatureVerifier getPublicKeySignatureVerifier(PublicKey key, SignatureAlgorithm algo) {
+        if (algo == null) {
+            LOG.warning("No signature algorithm was defined");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        
+        if (key instanceof RSAPublicKey) {
+            return new PublicKeyJwsSignatureVerifier(key, algo);
+        } else if (key instanceof ECPublicKey) {
+            return new EcDsaJwsSignatureVerifier(key, algo);
+        }
+        
+        return null;
+    }
+    public static JwsSignatureVerifier getHmacSignatureVerifier(byte[] key, SignatureAlgorithm algo) {
+        if (algo == null) {
+            LOG.warning("No signature algorithm was defined");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        
+        if (AlgorithmUtils.isHmacSign(algo.getJwaName())) {
+            return new HmacJwsSignatureVerifier(key, algo);
+        }
+        return null;
+    }
+    
+    public static Map<SignatureAlgorithm, List<JwsJsonSignatureEntry>> getJwsJsonSignatureMap(
+        List<JwsJsonSignatureEntry> signatures) {
+        Map<SignatureAlgorithm, List<JwsJsonSignatureEntry>> map = new HashMap<>();
+        for (JwsJsonSignatureEntry entry : signatures) {
+            SignatureAlgorithm sigAlgorithm = entry.getUnionHeader().getSignatureAlgorithm();
+            List<JwsJsonSignatureEntry> entries = map.get(sigAlgorithm);
+            if (entries == null) {
+                entries = new ArrayList<>();
+            }
+            entries.add(entry);
+            map.put(sigAlgorithm, entries);
+        }
+        return map;
+    }
+    
+    public static JwsSignatureProvider loadSignatureProvider(boolean required) {
+        return loadSignatureProvider(null, required);    
+    }
+    public static JwsSignatureProvider loadSignatureProvider(JwsHeaders headers, boolean required) {
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
+                                                                  RSSEC_SIGNATURE_OUT_PROPS, RSSEC_SIGNATURE_PROPS);
+        if (props == null) {
+            return null;
+        }
+        JwsSignatureProvider theSigProvider = loadSignatureProvider(m, props, headers, false);
+        if (headers != null) {
+            headers.setSignatureAlgorithm(theSigProvider.getAlgorithm());
+        }
+        return theSigProvider;
+    }
+    public static JwsSignatureVerifier loadSignatureVerifier(boolean required) {
+        return loadSignatureVerifier(null, required);
+    }
+    public static JwsSignatureVerifier loadSignatureVerifier(JwsHeaders headers, boolean required) {
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
+                                                                  RSSEC_SIGNATURE_IN_PROPS, RSSEC_SIGNATURE_PROPS);
+        if (props == null) {
+            return null;
+        }
+        return loadSignatureVerifier(m, props, headers, false);
+    }
+    public static List<JwsSignatureProvider> loadSignatureProviders(String propLoc, Message m) {
+        Properties props = loadJwsProperties(m, propLoc);
+        JwsSignatureProvider theSigProvider = loadSignatureProvider(m, props, null, true);
+        if (theSigProvider != null) {
+            return Collections.singletonList(theSigProvider);
+        }
+        List<JwsSignatureProvider> theSigProviders = null; 
+        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+            List<JsonWebKey> jwks = JwkUtils.loadJsonWebKeys(m, props, KeyOperation.SIGN);
+            if (jwks != null) {
+                theSigProviders = new ArrayList<JwsSignatureProvider>(jwks.size());
+                for (JsonWebKey jwk : jwks) {
+                    theSigProviders.add(JwsUtils.getSignatureProvider(jwk));
+                }
+            }
+        }
+        if (theSigProviders == null) {
+            LOG.warning("Providers are not available");
+            throw new JwsException(JwsException.Error.NO_PROVIDER);
+        }
+        return theSigProviders;
+    }
+    
+    public static List<JwsSignatureVerifier> loadSignatureVerifiers(String propLoc, Message m) {
+        Properties props = loadJwsProperties(m, propLoc);
+        JwsSignatureVerifier theVerifier = loadSignatureVerifier(m, props, null, true);
+        if (theVerifier != null) {
+            return Collections.singletonList(theVerifier);
+        }
+        List<JwsSignatureVerifier> theVerifiers = null; 
+        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+            List<JsonWebKey> jwks = JwkUtils.loadJsonWebKeys(m, props, KeyOperation.VERIFY);
+            if (jwks != null) {
+                theVerifiers = new ArrayList<JwsSignatureVerifier>(jwks.size());
+                for (JsonWebKey jwk : jwks) {
+                    theVerifiers.add(JwsUtils.getSignatureVerifier(jwk));
+                }
+            }
+        }
+        if (theVerifiers == null) {
+            LOG.warning("Verifiers are not available");
+            throw new JwsException(JwsException.Error.NO_VERIFIER);
+        }
+        return theVerifiers;
+    }
+    public static boolean validateCriticalHeaders(JoseHeaders headers) {
+        //TODO: validate JWS specific constraints
+        return JoseUtils.validateCriticalHeaders(headers);
+    }
+    private static JwsSignatureProvider loadSignatureProvider(Message m, 
+                                                              Properties props,
+                                                              JoseHeaders headers,
+                                                              boolean ignoreNullProvider) {
+        JwsSignatureProvider theSigProvider = null;
+        
+        boolean reportPublicKey = headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, RSSEC_REPORT_KEY_PROP, 
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_PROP));
+        boolean reportPublicKeyId = 
+            headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, RSSEC_REPORT_KEY_ID_PROP,
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_ID_PROP));
+        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+            JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.SIGN);
+            if (jwk != null) {
+                String signatureAlgo = getSignatureAlgo(m, props, jwk.getAlgorithm(), getDefaultKeyAlgo(jwk));
+                theSigProvider = JwsUtils.getSignatureProvider(jwk, SignatureAlgorithm.getAlgorithm(signatureAlgo));
+                if (reportPublicKey || reportPublicKeyId) {
+                    JwkUtils.setPublicKeyInfo(jwk, headers, signatureAlgo, reportPublicKey, reportPublicKeyId);
+                }
+            }
+        } else {
+            String signatureAlgo = getSignatureAlgo(m, props, null, null);
+            PrivateKey pk = KeyManagementUtils.loadPrivateKey(m, props, KeyOperation.SIGN);
+            theSigProvider = getPrivateKeySignatureProvider(pk, 
+                                                            SignatureAlgorithm.getAlgorithm(signatureAlgo));
+            if (reportPublicKey) {
+                headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
+            }
+        }
+        if (theSigProvider == null && !ignoreNullProvider) {
+            LOG.warning("Provider is not available");
+            throw new JwsException(JwsException.Error.NO_PROVIDER);
+        }
+        return theSigProvider;
+    }
+    private static JwsSignatureVerifier loadSignatureVerifier(Message m, 
+                                                              Properties props,
+                                                              JwsHeaders inHeaders, 
+                                                              boolean ignoreNullVerifier) {
+        JwsSignatureVerifier theVerifier = null;
+        String inHeaderKid = null;
+        if (inHeaders != null) {
+            inHeaderKid = inHeaders.getKeyId();
+            //TODO: optionally validate inHeaders.getAlgorithm against a property in props
+            if (inHeaders.getHeader(JoseConstants.HEADER_JSON_WEB_KEY) != null) {
+                JsonWebKey publicJwk = inHeaders.getJsonWebKey();
+                if (inHeaderKid != null && !inHeaderKid.equals(publicJwk.getKeyId())
+                    || !MessageUtils.getContextualBoolean(m, KeyManagementUtils.RSSEC_ACCEPT_PUBLIC_KEY_PROP, true)) {
+                    throw new JwsException(JwsException.Error.INVALID_KEY);
+                }
+                return getSignatureVerifier(publicJwk, 
+                                            inHeaders.getSignatureAlgorithm());
+            } else if (inHeaders.getHeader(JoseConstants.HEADER_X509_CHAIN) != null) {
+                List<X509Certificate> chain = KeyManagementUtils.toX509CertificateChain(inHeaders.getX509Chain());
+                KeyManagementUtils.validateCertificateChain(props, chain);
+                return getPublicKeySignatureVerifier(chain.get(0).getPublicKey(), 
+                                                     inHeaders.getSignatureAlgorithm());
+            }
+        }
+        
+        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+            JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.VERIFY, inHeaderKid);
+            if (jwk != null) {
+                String signatureAlgo = getSignatureAlgo(m, props, jwk.getAlgorithm(), getDefaultKeyAlgo(jwk));
+                theVerifier = getSignatureVerifier(jwk, SignatureAlgorithm.getAlgorithm(signatureAlgo));
+            }
+            
+        } else {
+            String signatureAlgo = getSignatureAlgo(m, props, null, null);
+            theVerifier = getPublicKeySignatureVerifier(
+                              KeyManagementUtils.loadPublicKey(m, props), 
+                              SignatureAlgorithm.getAlgorithm(signatureAlgo));
+        }
+        if (theVerifier == null && !ignoreNullVerifier) {
+            LOG.warning("Verifier is not available");
+            throw new JwsException(JwsException.Error.NO_VERIFIER);
+        }
+        return theVerifier;
+    }
+    private static Properties loadJwsProperties(Message m, String propLoc) {
+        try {
+            return JoseUtils.loadProperties(propLoc, m.getExchange().getBus());
+        } catch (Exception ex) {
+            LOG.warning("JWS init properties are not available");
+            throw new JwsException(JwsException.Error.NO_INIT_PROPERTIES);
+        }
+    }
+    private static String getSignatureAlgo(Message m, Properties props, String algo, String defaultAlgo) {
+        if (algo == null) {
+            if (defaultAlgo == null) {
+                defaultAlgo = AlgorithmUtils.RS_SHA_256_ALGO;
+            }
+            return KeyManagementUtils.getKeyAlgorithm(m, props, JSON_WEB_SIGNATURE_ALGO_PROP, defaultAlgo);
+        }
+        return algo;
+    }
+    private static String getDefaultKeyAlgo(JsonWebKey jwk) {
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.OCTET == keyType) {
+            return AlgorithmUtils.HMAC_SHA_256_ALGO;
+        } else if (KeyType.EC == keyType) {
+            return AlgorithmUtils.ES_SHA_256_ALGO;
+        } else {
+            return AlgorithmUtils.RS_SHA_256_ALGO;
+        }
+    }
+    private static JwsCompactConsumer verify(JwsSignatureVerifier v, String content) {
+        JwsCompactConsumer jws = new JwsCompactConsumer(content);
+        if (!jws.verifySignatureWith(v)) {
+            throw new JwsException(JwsException.Error.INVALID_SIGNATURE);
+        }
+        return jws;
+    }
+    private static String sign(JwsSignatureProvider jwsSig, String content, String ct) {
+        JwsHeaders headers = new JwsHeaders();
+        if (ct != null) {
+            headers.setContentType(ct);
+        }
+        JwsCompactProducer jws = new JwsCompactProducer(headers, content);
+        jws.signWith(jwsSig);
+        return jws.getSignedEncodedJws();
+    }
+    public static void validateJwsCertificateChain(List<X509Certificate> certs) {
+        
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, true, 
+                                                                  RSSEC_SIGNATURE_IN_PROPS, RSSEC_SIGNATURE_PROPS);
+        KeyManagementUtils.validateCertificateChain(props, certs);
+    }
+    public static boolean isPayloadUnencoded(JwsHeaders jwsHeaders) {
+        return jwsHeaders.getPayloadEncodingStatus() == Boolean.FALSE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
new file mode 100644
index 0000000..6ed31fd
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
@@ -0,0 +1,55 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public class NoneJwsSignatureProvider implements JwsSignatureProvider {
+
+    @Override
+    public SignatureAlgorithm getAlgorithm() {
+        return SignatureAlgorithm.NONE;
+    }
+
+    @Override
+    public JwsSignature createJwsSignature(JwsHeaders headers) {
+        return new NoneJwsSignature();
+    }
+
+    @Override
+    public byte[] sign(JwsHeaders headers, byte[] content) {
+        JwsSignature sig = createJwsSignature(headers);
+        sig.update(content, 0, content.length);
+        return sig.sign();
+    }
+    private static class NoneJwsSignature implements JwsSignature {
+
+        @Override
+        public void update(byte[] src, int off, int len) {
+            // complete
+        }
+
+        @Override
+        public byte[] sign() {
+            return new byte[]{};
+        }
+        
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
new file mode 100644
index 0000000..441261b
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
@@ -0,0 +1,36 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public class NoneJwsSignatureVerifier implements JwsSignatureVerifier {
+
+    @Override
+    public boolean verify(JwsHeaders headers, String unsignedText, byte[] signature) {
+        return headers.getSignatureAlgorithm() == getAlgorithm() 
+            && signature.length == 0;
+    }
+
+    @Override
+    public SignatureAlgorithm getAlgorithm() {
+        return SignatureAlgorithm.NONE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
new file mode 100644
index 0000000..476d90f
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
@@ -0,0 +1,91 @@
+/**
+ * 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.jws;
+
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+
+public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider {
+    private PrivateKey key;
+    private SecureRandom random; 
+    private AlgorithmParameterSpec signatureSpec;
+    
+    public PrivateKeyJwsSignatureProvider(PrivateKey key, SignatureAlgorithm algo) {
+        this(key, null, algo);
+    }
+    public PrivateKeyJwsSignatureProvider(PrivateKey key, AlgorithmParameterSpec spec, SignatureAlgorithm algo) {
+        this(key, null, spec, algo);
+    }
+    public PrivateKeyJwsSignatureProvider(PrivateKey key, SecureRandom random, 
+                                          AlgorithmParameterSpec spec, SignatureAlgorithm algo) {
+        super(algo);
+        this.key = key;
+        this.random = random;
+        this.signatureSpec = spec;
+    }
+    protected JwsSignature doCreateJwsSignature(JwsHeaders headers) {
+        final String sigAlgo = headers.getSignatureAlgorithm().getJwaName();
+        final Signature s = CryptoUtils.getSignature(key, 
+                                                     AlgorithmUtils.toJavaName(sigAlgo),
+                                                     random,
+                                                     signatureSpec);
+        return doCreateJwsSignature(s);
+    }
+    protected JwsSignature doCreateJwsSignature(Signature s) {
+        return new PrivateKeyJwsSignature(s);
+    }
+    
+    @Override
+    protected boolean isValidAlgorithmFamily(String algo) {
+        return AlgorithmUtils.isRsaSign(algo);
+    }
+
+    protected static class PrivateKeyJwsSignature implements JwsSignature {
+        private Signature s;
+        public PrivateKeyJwsSignature(Signature s) {
+            this.s = s;
+        }
+        @Override
+        public void update(byte[] src, int off, int len) {
+            try {
+                s.update(src, off, len);
+            } catch (SignatureException ex) {
+                throw new JwsException(JwsException.Error.SIGNATURE_FAILURE, ex);
+            }
+        }
+
+        @Override
+        public byte[] sign() {
+            try {
+                return s.sign();
+            } catch (SignatureException ex) {
+                throw new JwsException(JwsException.Error.SIGNATURE_FAILURE, ex);
+            }
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java
new file mode 100644
index 0000000..917890f
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.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.jws;
+
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+
+public class PublicKeyJwsSignatureVerifier implements JwsSignatureVerifier {
+    protected static final Logger LOG = LogUtils.getL7dLogger(PublicKeyJwsSignatureVerifier.class);
+    private PublicKey key;
+    private AlgorithmParameterSpec signatureSpec;
+    private SignatureAlgorithm supportedAlgo;
+    
+    public PublicKeyJwsSignatureVerifier(PublicKey key, SignatureAlgorithm supportedAlgorithm) {
+        this(key, null, supportedAlgorithm);
+    }
+    public PublicKeyJwsSignatureVerifier(PublicKey key, AlgorithmParameterSpec spec, SignatureAlgorithm supportedAlgo) {
+        this.key = key;
+        this.signatureSpec = spec;
+        this.supportedAlgo = supportedAlgo;
+    }
+    @Override
+    public boolean verify(JwsHeaders headers, String unsignedText, byte[] signature) {
+        try {
+            return CryptoUtils.verifySignature(StringUtils.toBytesUTF8(unsignedText), 
+                                               signature, 
+                                               key, 
+                                               AlgorithmUtils.toJavaName(checkAlgorithm(
+                                                                              headers.getSignatureAlgorithm())),
+                                               signatureSpec);
+        } catch (Exception ex) {
+            LOG.warning("Invalid signature: " + ex.getMessage());
+            throw new JwsException(JwsException.Error.INVALID_SIGNATURE, ex);
+        }
+    }
+    protected String checkAlgorithm(SignatureAlgorithm sigAlgo) {
+        String algo = sigAlgo.getJwaName();
+        if (algo == null) {
+            LOG.warning("Signature algorithm is not set");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        if (!isValidAlgorithmFamily(algo)
+            || !algo.equals(supportedAlgo.getJwaName())) {
+            LOG.warning("Invalid signature algorithm: " + algo);
+            throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
+        }
+        return algo;
+    }
+    protected boolean isValidAlgorithmFamily(String algo) {
+        return AlgorithmUtils.isRsaSign(algo);
+    }
+    @Override
+    public SignatureAlgorithm getAlgorithm() {
+        return supportedAlgo;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
new file mode 100644
index 0000000..d4cdf48
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
@@ -0,0 +1,96 @@
+/**
+ * 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.jwt;
+
+import org.apache.cxf.rs.security.jose.AbstractJoseConsumer;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+
+public abstract class AbstractJoseJwtConsumer extends AbstractJoseConsumer {
+    private boolean jwsRequired = true;
+    private boolean jweRequired;
+    
+    
+    protected JwtToken getJwtToken(String wrappedJwtToken) {
+        return getJwtToken(wrappedJwtToken, null, null);
+    }
+    protected JwtToken getJwtToken(String wrappedJwtToken,
+                                   JweDecryptionProvider jweDecryptor,
+                                   JwsSignatureVerifier theSigVerifier) {
+        if (!isJwsRequired() && !isJweRequired()) {
+            throw new JwtException("Unable to process JWT");
+        }
+        
+        if (isJweRequired()) {
+            if (jweDecryptor == null) {
+                jweDecryptor = getInitializedDecryptionProvider();
+            }
+            if (jweDecryptor == null) {
+                throw new JwtException("Unable to decrypt JWT");
+            }
+            
+            if (!isJwsRequired()) {
+                return new JweJwtCompactConsumer(wrappedJwtToken).decryptWith(jweDecryptor);    
+            }
+            wrappedJwtToken = jweDecryptor.decrypt(wrappedJwtToken).getContentText();
+        }
+        
+
+        JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(wrappedJwtToken);
+        JwtToken jwt = jwtConsumer.getJwtToken();
+        if (isJwsRequired()) {
+            if (theSigVerifier == null) {
+                theSigVerifier = getInitializedSignatureVerifier(jwt);
+            }
+            if (theSigVerifier == null) {
+                throw new JwtException("Unable to validate JWT");
+            }
+            
+            if (!jwtConsumer.verifySignatureWith(theSigVerifier)) {
+                throw new JwtException("Invalid Signature");
+            }
+        }
+        
+        validateToken(jwt);
+        return jwt; 
+    }
+    protected JwsSignatureVerifier getInitializedSignatureVerifier(JwtToken jwt) {
+        return super.getInitializedSignatureVerifier();
+    }
+    protected void validateToken(JwtToken jwt) {
+    }
+    public boolean isJwsRequired() {
+        return jwsRequired;
+    }
+
+    public void setJwsRequired(boolean jwsRequired) {
+        this.jwsRequired = jwsRequired;
+    }
+
+    public boolean isJweRequired() {
+        return jweRequired;
+    }
+
+    public void setJweRequired(boolean jweRequired) {
+        this.jweRequired = jweRequired;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
new file mode 100644
index 0000000..cb7d394
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
@@ -0,0 +1,84 @@
+/**
+ * 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.jwt;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.AbstractJoseProducer;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+
+public abstract class AbstractJoseJwtProducer extends AbstractJoseProducer {
+    private boolean jwsRequired = true;
+    private boolean jweRequired;
+    
+    protected String processJwt(JwtToken jwt) {
+        return processJwt(jwt, null, null);
+    }
+    protected String processJwt(JwtToken jwt,
+                                JweEncryptionProvider theEncProvider,
+                                JwsSignatureProvider theSigProvider) {
+        if (!isJwsRequired() && !isJweRequired()) {
+            throw new JwtException("Unable to secure JWT");
+        }
+        String data = null;
+        
+        if (isJweRequired() && theEncProvider == null) {
+            theEncProvider = getInitializedEncryptionProvider();
+            if (theEncProvider == null) {
+                throw new JwtException("Unable to encrypt JWT");
+            }
+        }
+        
+        if (isJwsRequired()) {
+            if (theSigProvider == null) {
+                theSigProvider = getInitializedSignatureProvider();
+            }
+            if (theSigProvider == null) {
+                throw new JwtException("Unable to sign JWT");
+            }
+            JwsJwtCompactProducer jws = new JwsJwtCompactProducer(jwt); 
+            data = jws.signWith(theSigProvider);
+            if (theEncProvider != null) {
+                data = theEncProvider.encrypt(StringUtils.toBytesUTF8(data), null);
+            }
+        } else {
+            JweJwtCompactProducer jwe = new JweJwtCompactProducer(jwt);
+            data = jwe.encryptWith(theEncProvider);
+        }
+        return data;
+    }
+
+    public boolean isJwsRequired() {
+        return jwsRequired;
+    }
+
+    public void setJwsRequired(boolean jwsRequired) {
+        this.jwsRequired = jwsRequired;
+    }
+
+    public boolean isJweRequired() {
+        return jweRequired;
+    }
+
+    public void setJweRequired(boolean jweRequired) {
+        this.jweRequired = jweRequired;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java
new file mode 100644
index 0000000..871e57a
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java
@@ -0,0 +1,102 @@
+/**
+ * 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.jwt;
+
+import java.util.Map;
+
+import org.apache.cxf.jaxrs.provider.json.JsonMapObject;
+
+
+
+
+public class JwtClaims extends JsonMapObject {
+    
+    public JwtClaims() {
+    }
+    
+    public JwtClaims(Map<String, Object> values) {
+        super(values);
+    }
+    
+    public void setIssuer(String issuer) {
+        setClaim(JwtConstants.CLAIM_ISSUER, issuer);
+    }
+    
+    public String getIssuer() {
+        return (String)getClaim(JwtConstants.CLAIM_ISSUER);
+    }
+    
+    public void setSubject(String subject) {
+        setClaim(JwtConstants.CLAIM_SUBJECT, subject);
+    }
+    
+    public String getSubject() {
+        return (String)getClaim(JwtConstants.CLAIM_SUBJECT);
+    }
+    
+    public void setAudience(String audience) {
+        setClaim(JwtConstants.CLAIM_AUDIENCE, audience);
+    }
+    
+    public String getAudience() {
+        return (String)getClaim(JwtConstants.CLAIM_AUDIENCE);
+    }
+    
+    public void setExpiryTime(Long expiresIn) {
+        setClaim(JwtConstants.CLAIM_EXPIRY, expiresIn);
+    }
+    
+    public Long getExpiryTime() {
+        return getLongProperty(JwtConstants.CLAIM_EXPIRY);
+    }
+    
+    public void setNotBefore(Long notBefore) {
+        setClaim(JwtConstants.CLAIM_NOT_BEFORE, notBefore);
+    }
+    
+    public Long getNotBefore() {
+        return getLongProperty(JwtConstants.CLAIM_NOT_BEFORE);
+    }
+    
+    public void setIssuedAt(Long issuedAt) {
+        setClaim(JwtConstants.CLAIM_ISSUED_AT, issuedAt);
+    }
+    
+    public Long getIssuedAt() {
+        return getLongProperty(JwtConstants.CLAIM_ISSUED_AT);
+    }
+    
+    public void setTokenId(String id) {
+        setClaim(JwtConstants.CLAIM_JWT_ID, id);
+    }
+    
+    public String getTokenId() {
+        return (String)getClaim(JwtConstants.CLAIM_JWT_ID);
+    }
+    
+    public JwtClaims setClaim(String name, Object value) {
+        setProperty(name, value);
+        return this;
+    }
+    
+    public Object getClaim(String name) {
+        return getProperty(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
new file mode 100644
index 0000000..bdbb544
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
@@ -0,0 +1,38 @@
+/**
+ * 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.jwt;
+
+public final class JwtConstants {
+    
+    public static final String CLAIM_ISSUER = "iss";
+    public static final String CLAIM_SUBJECT = "sub";
+    public static final String CLAIM_AUDIENCE = "aud";
+    public static final String CLAIM_EXPIRY = "exp";
+    public static final String CLAIM_NOT_BEFORE = "nbf";
+    public static final String CLAIM_ISSUED_AT = "iat";
+    public static final String CLAIM_JWT_ID = "jti";
+    
+    public static final String JWT_TOKEN = "jwt.token";
+    
+        
+    private JwtConstants() {
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtException.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtException.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtException.java
new file mode 100644
index 0000000..84314bd
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtException.java
@@ -0,0 +1,35 @@
+/**
+ * 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.jwt;
+
+import org.apache.cxf.rs.security.jose.JoseException;
+
+public class JwtException extends JoseException {
+
+    private static final long serialVersionUID = 4118589816228511524L;
+    public JwtException() {
+
+    }
+    public JwtException(String error) {
+        super(error);
+    }
+    public JwtException(Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java
new file mode 100644
index 0000000..f8be716
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.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.jwt;
+
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+
+
+
+public class JwtToken {
+    private JoseHeaders headers;
+    private JwtClaims claims;
+    public JwtToken(JwtClaims claims) {
+        this(new JoseHeaders() { }, claims);
+    }
+    public JwtToken(JoseHeaders headers, JwtClaims claims) {
+        this.headers = headers;
+        this.claims = claims;
+    }
+    public JoseHeaders getHeaders() {
+        return headers;
+    }
+    public JwtClaims getClaims() {
+        return claims;
+    }
+    public Object getHeader(String name) {
+        return headers.getHeader(name);
+    }
+    public Object getClaim(String name) {
+        return claims.getClaim(name);
+    }
+    public int hashCode() { 
+        return headers.hashCode() + 37 * claims.hashCode();
+    }
+    
+    public boolean equals(Object obj) {
+        return obj instanceof JwtToken 
+            && ((JwtToken)obj).headers.equals(this.headers)
+            && ((JwtToken)obj).claims.equals(this.claims);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e40ea35/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
new file mode 100644
index 0000000..0ebf8a3
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
@@ -0,0 +1,55 @@
+/**
+ * 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.jwt;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter;
+
+
+
+
+public class JwtTokenReaderWriter extends JsonMapObjectReaderWriter {
+    private static final Set<String> DATE_PROPERTIES = 
+        new HashSet<String>(Arrays.asList(JwtConstants.CLAIM_EXPIRY, 
+                                          JwtConstants.CLAIM_ISSUED_AT, 
+                                          JwtConstants.CLAIM_NOT_BEFORE));
+
+    public String claimsToJson(JwtClaims claims) {
+        return toJson(claims);
+    }
+
+    public JwtClaims fromJsonClaims(String claimsJson) {
+        JwtClaims claims = new JwtClaims();
+        fromJson(claims, claimsJson);
+        return claims;
+        
+    }
+    
+    @Override
+    protected Object readPrimitiveValue(String name, String json, int from, int to) {
+        Object value = super.readPrimitiveValue(name, json, from, to);
+        if (DATE_PROPERTIES.contains(name)) {
+            value = Long.valueOf(value.toString());
+        }
+        return value;
+    }
+}


Mime
View raw message