cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject git commit: [CXF-5954] Prototyping basic JWK support
Date Wed, 03 Sep 2014 16:39:51 GMT
Repository: cxf
Updated Branches:
  refs/heads/3.0.x-fixes 29efbac39 -> e6df01723


[CXF-5954] Prototyping basic JWK support


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/e6df0172
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/e6df0172
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/e6df0172

Branch: refs/heads/3.0.x-fixes
Commit: e6df01723bf9d091ef2fae86c12aebe95a7141b7
Parents: 29efbac
Author: Sergey Beryozkin <sberyozkin@talend.com>
Authored: Wed Sep 3 17:38:06 2014 +0100
Committer: Sergey Beryozkin <sberyozkin@talend.com>
Committed: Wed Sep 3 17:39:32 2014 +0100

----------------------------------------------------------------------
 .../cxf/rs/security/oauth2/jwk/JsonWebKey.java  | 159 ++++++++++++++
 .../oauth2/jwk/JsonWebKeyReaderWriter.java      |  45 ++++
 .../cxf/rs/security/oauth2/jwk/JsonWebKeys.java |  70 ++++++
 .../jwt/AbstractJwtObjectReaderWriter.java      | 212 +++++++++++++++++++
 .../cxf/rs/security/oauth2/jwt/JwtHeaders.java  |   2 +-
 .../oauth2/jwt/JwtTokenReaderWriter.java        | 190 +----------------
 .../rs/security/oauth2/jwt/jwk/JsonWebKey.java  | 141 ------------
 .../rs/security/oauth2/jwk/JsonWebKeyTest.java  | 171 +++++++++++++++
 .../rs/security/oauth2/jwk/jwkPrivateSet.txt    |  23 ++
 .../cxf/rs/security/oauth2/jwk/jwkPublicSet.txt |  17 ++
 .../cxf/rs/security/oauth2/jwk/jwkSecretSet.txt |  13 ++
 .../oauth2/jws/JwsCompactReaderWriterTest.java  |   2 +-
 12 files changed, 714 insertions(+), 331 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java
new file mode 100644
index 0000000..d251c0b
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java
@@ -0,0 +1,159 @@
+/**
+ * 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.oauth2.jwk;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.oauth2.jwt.AbstractJwtObject;
+import org.apache.cxf.rs.security.oauth2.jwt.JwtConstants;
+
+
+public class JsonWebKey extends AbstractJwtObject {
+    
+    public static final String KEY_TYPE = "kty";
+    public static final String PUBLIC_KEY_USE = "use";
+    public static final String KEY_OPERATIONS = "key_ops";
+    public static final String KEY_ALGO = JwtConstants.HEADER_ALGORITHM;
+    public static final String KEY_ID = JwtConstants.HEADER_KEY_ID;
+    public static final String X509_URL = JwtConstants.HEADER_X509_URL;
+    public static final String X509_CHAIN = JwtConstants.HEADER_X509_CHAIN;
+    public static final String X509_THUMBPRINT = JwtConstants.HEADER_X509_THUMBPRINT;
+    public static final String X509_THUMBPRINT_SHA256 = JwtConstants.HEADER_X509_THUMBPRINT_SHA256;
+    
+    public static final String KEY_TYPE_RSA = "RSA";
+    public static final String RSA_MODULUS = "n";
+    public static final String RSA_PUBLIC_EXP = "e";
+    public static final String RSA_PRIVATE_EXP = "d";
+    public static final String RSA_FIRST_PRIME_FACTOR = "p";
+    public static final String RSA_SECOND_PRIME_FACTOR = "q";
+    public static final String RSA_FIRST_PRIME_CRT = "dp";
+    public static final String RSA_SECOND_PRIME_CRT = "dq";
+    public static final String RSA_FIRST_CRT_COEFFICIENT = "qi";
+        
+    public static final String KEY_TYPE_OCTET = "oct";
+    public static final String OCTET_KEY_VALUE = "k";
+    
+    public static final String KEY_TYPE_ELLIPTIC = "EC";
+    public static final String EC_CURVE = "crv";
+    public static final String EC_CURVE_P256 = "P-256";
+    public static final String EC_CURVE_P384 = "P-384";
+    public static final String EC_CURVE_P512 = "P-512";
+    public static final String EC_X_COORDINATE = "x";
+    public static final String EC_Y_COORDINATE = "y";
+    public static final String EC_PRIVATE_KEY = "d";
+    
+    public static final String PUBLIC_KEY_USE_SIGN = "sig";
+    public static final String PUBLIC_KEY_USE_ENCRYPT = "enc";
+    
+    public static final String KEY_OPER_SIGN = "sign";
+    public static final String KEY_OPER_VERIFY = "verify";
+    public static final String KEY_OPER_ENCRYPT = "encrypt";
+    public static final String KEY_OPER_DECRYPT = "decrypt";
+    
+    public JsonWebKey() {
+        
+    }
+    
+    public JsonWebKey(Map<String, Object> values) {
+        super(values);
+    }
+    
+    public void setKeyType(String keyType) {
+        super.setValue(KEY_TYPE, keyType);
+    }
+
+    public String getKeyType() {
+        return (String)super.getValue(KEY_TYPE);
+    }
+
+    public void setPublicKeyUse(String use) {
+        super.setValue(PUBLIC_KEY_USE, use);
+    }
+    
+    public String getPublicKeyUse() {
+        return (String)super.getValue(PUBLIC_KEY_USE);
+    }
+
+    public void setKeyOperation(List<String> keyOperation) {
+        super.setValue(KEY_OPERATIONS, keyOperation);
+    }
+
+    public List<String> getKeyOperation() {
+        return CastUtils.cast((List<?>)super.getValue(KEY_OPERATIONS));
+    }
+    
+    public void setAlgorithm(String algorithm) {
+        super.setValue(KEY_ALGO, algorithm);
+    }
+
+    public String getAlgorithm() {
+        return (String)super.getValue(KEY_ALGO);
+    }
+    
+    public void setKid(String kid) {
+        super.setValue(KEY_ID, kid);
+    }
+
+    public String getKid() {
+        return (String)super.getValue(KEY_ID);
+    }
+    
+    public void setX509Url(String x509Url) {
+        super.setValue(X509_URL, x509Url);
+    }
+    
+    public String getX509Url() {
+        return (String)super.getValue(X509_URL);
+    }
+
+    public void setX509Chain(String x509Chain) {
+        super.setValue(X509_CHAIN, x509Chain);
+    }
+
+    public String getX509Chain() {
+        return (String)super.getValue(X509_CHAIN);
+    }
+    
+    public void setX509Thumbprint(String x509Thumbprint) {
+        super.setValue(X509_THUMBPRINT, x509Thumbprint);
+    }
+    
+    public String getX509Thumbprint() {
+        return (String)super.getValue(X509_THUMBPRINT);
+    }
+    
+    public void setX509ThumbprintSHA256(String x509Thumbprint) {
+        super.setValue(X509_THUMBPRINT_SHA256, x509Thumbprint);
+    }
+    
+    public String getX509ThumbprintSHA256() {
+        return (String)super.getValue(X509_THUMBPRINT_SHA256);
+    }
+    
+    public JsonWebKey setProperty(String name, Object value) {
+        super.setValue(name, value);
+        return this;
+    }
+    
+    public Object getProperty(String name) {
+        return super.getValue(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyReaderWriter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyReaderWriter.java
new file mode 100644
index 0000000..56f22e0
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyReaderWriter.java
@@ -0,0 +1,45 @@
+/**
+ * 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.oauth2.jwk;
+
+import org.apache.cxf.rs.security.oauth2.jwt.AbstractJwtObjectReaderWriter;
+
+
+
+
+public class JsonWebKeyReaderWriter extends AbstractJwtObjectReaderWriter {
+    public String jwkToJson(JsonWebKey jwk) {
+        return toJson(jwk);
+    }
+
+    public String jwksToJson(JsonWebKeys jwks) {
+        return toJson(jwks);
+    }
+
+    public JsonWebKey jsonToJwk(String jwkJson) {
+        JsonWebKey jwk = new JsonWebKey();
+        fromJsonInternal(jwk, jwkJson);
+        return jwk;
+    }
+    public JsonWebKeys jsonToJwks(String jwksJson) {
+        JsonWebKeys jwks = new JsonWebKeys();
+        fromJsonInternal(jwks, jwksJson);
+        return jwks;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeys.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeys.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeys.java
new file mode 100644
index 0000000..3b699f4
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeys.java
@@ -0,0 +1,70 @@
+/**
+ * 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.oauth2.jwk;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.oauth2.jwt.AbstractJwtObject;
+
+public class JsonWebKeys extends AbstractJwtObject {
+    public static final String KEYS_PROPERTY = "keys";
+    public List<JsonWebKey> getKeys() {
+        List<?> list = (List<?>)super.getValue(KEYS_PROPERTY);
+        if (list != null && !list.isEmpty()) {
+            Object first = list.get(0);
+            if (first instanceof JsonWebKey) {
+                return CastUtils.cast(list);
+            } else {
+                List<JsonWebKey> keys = new LinkedList<JsonWebKey>();
+                List<Map<String, Object>> listOfMaps = 
+                    CastUtils.cast((List<?>)super.getValue(KEYS_PROPERTY));
+                for (Map<String, Object> map : listOfMaps) {
+                    keys.add(new JsonWebKey(map));
+                }
+                return keys;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    public void setKeys(List<JsonWebKey> keys) {
+        super.setValue(KEYS_PROPERTY, keys);
+    }
+    
+    public Map<String, JsonWebKey> getKeysMap() {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, JsonWebKey> map = new LinkedHashMap<String, JsonWebKey>();
+        for (JsonWebKey key : keys) {
+            String kid = key.getKid();
+            if (kid != null) {
+                map.put(kid, key);
+            }
+        }
+        return map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/AbstractJwtObjectReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/AbstractJwtObjectReaderWriter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/AbstractJwtObjectReaderWriter.java
new file mode 100644
index 0000000..b525bc2
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/AbstractJwtObjectReaderWriter.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.oauth2.jwt;
+
+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;
+
+
+
+public class AbstractJwtObjectReaderWriter {
+    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(AbstractJwtObject 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 (AbstractJwtObject.class.isAssignableFrom(value.getClass())) {
+            sb.append(toJson((AbstractJwtObject)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(AbstractJwtObject jwt, String json) {
+        String theJson = json.trim();
+        Map<String, Object> values = readJwtObjectAsMap(theJson.substring(1, theJson.length() - 1));
+        fromJsonInternal(jwt, values);
+    }
+    
+    protected void fromJsonInternal(AbstractJwtObject jwt, Map<String, Object> values) {
+        for (Map.Entry<String, Object> entry : values.entrySet()) {
+            jwt.setValue(entry.getKey(), entry.getValue());
+        }
+    }
+    
+    protected Map<String, Object> readJwtObjectAsMap(String json) {
+        Map<String, Object> values = new LinkedHashMap<String, Object>();
+        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);
+                values.put(name, readJwtObjectAsMap(newJson));
+                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;
+            }
+            
+        }
+        return values;
+    }
+    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);
+                values.add(readJwtObjectAsMap(json.substring(i + 1, closingIndex)));
+                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;
+    }
+
+    
+
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtHeaders.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtHeaders.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtHeaders.java
index 7ca0ba5..240c084 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtHeaders.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtHeaders.java
@@ -23,7 +23,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.rs.security.oauth2.jwt.jwk.JsonWebKey;
+import org.apache.cxf.rs.security.oauth2.jwk.JsonWebKey;
 
 public class JwtHeaders extends AbstractJwtObject {
     

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtTokenReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtTokenReaderWriter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtTokenReaderWriter.java
index 2c20c11..5a287bb 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtTokenReaderWriter.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtTokenReaderWriter.java
@@ -18,25 +18,11 @@
  */
 package org.apache.cxf.rs.security.oauth2.jwt;
 
-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;
 
 
 
-public class JwtTokenReaderWriter implements JwtTokenReader, JwtTokenWriter {
-    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;
-    
+public class JwtTokenReaderWriter extends AbstractJwtObjectReaderWriter
+    implements JwtTokenReader, JwtTokenWriter {
     @Override
     public String headersToJson(JwtHeaders headers) {
         return toJson(headers);
@@ -78,176 +64,4 @@ public class JwtTokenReaderWriter implements JwtTokenReader, JwtTokenWriter {
     public JwtToken fromJson(JwtTokenJson pair) {
         return fromJson(pair.getHeadersJson(), pair.getClaimsJson());
     }
-    
-    private String toJson(AbstractJwtObject jwt) {
-        StringBuilder sb = new StringBuilder();
-        toJsonInternal(sb, jwt.asMap());
-        return sb.toString();
-    }
-
-    private 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("}");
-    }
-    
-    private void toJsonInternal(StringBuilder sb, Object[] array) {
-        toJsonInternal(sb, Arrays.asList(array));
-    }
-    
-    private 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")
-    private void toJsonInternal(StringBuilder sb, Object value, boolean hasNext) {
-        if (AbstractJwtObject.class.isAssignableFrom(value.getClass())) {
-            sb.append(toJson((AbstractJwtObject)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);
-        }
-        
-    }
-    
-    private void formatIfNeeded(StringBuilder sb) {
-        if (format) {
-            sb.append("\r\n ");
-        }
-    }
-        
-    private void fromJsonInternal(AbstractJwtObject jwt, String json) {
-        Map<String, Object> values = readJwtObjectAsMap(json.substring(1, json.length() - 1));
-        fromJsonInternal(jwt, values);
-    }
-    
-    private void fromJsonInternal(AbstractJwtObject jwt, Map<String, Object> values) {
-        for (Map.Entry<String, Object> entry : values.entrySet()) {
-            jwt.setValue(entry.getKey(), entry.getValue());
-        }
-    }
-    
-    private Map<String, Object> readJwtObjectAsMap(String json) {
-        Map<String, Object> values = new LinkedHashMap<String, Object>();
-        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);
-                values.put(name, readJwtObjectAsMap(newJson));
-                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;
-            }
-            
-        }
-        return values;
-    }
-    private 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);
-                values.add(readJwtObjectAsMap(json.substring(i + 1, closingIndex - 1)));
-                i = closingIndex + 1;
-            } else {
-                int commaIndex = getCommaIndex(json, i);
-                Object value = readPrimitiveValue(json, i, commaIndex);
-                values.add(value);
-                i = commaIndex + 1;
-            }
-        }
-        
-        return values;
-    }
-    private 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;
-    }
-    
-    private static int getCommaIndex(String json, int from) {
-        int commaIndex = json.indexOf(",", from);
-        if (commaIndex == -1) {
-            commaIndex = json.length();
-        }
-        return commaIndex;
-    }
-    private 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;
-    }
-    private boolean isWhiteSpace(char jsonChar) {
-        return jsonChar == ' ' || jsonChar == '\r' || jsonChar == '\n' || jsonChar == '\t';
-    }
-
-    public void setFormat(boolean format) {
-        this.format = format;
-    }
-
-    
-
-    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jwk/JsonWebKey.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jwk/JsonWebKey.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jwk/JsonWebKey.java
deleted file mode 100644
index 7445251..0000000
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jwk/JsonWebKey.java
+++ /dev/null
@@ -1,141 +0,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.
- */
-package org.apache.cxf.rs.security.oauth2.jwt.jwk;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.rs.security.oauth2.jwt.AbstractJwtObject;
-import org.apache.cxf.rs.security.oauth2.jwt.JwtConstants;
-
-
-public class JsonWebKey extends AbstractJwtObject {
-    
-    public static final String KEY_TYPE = "kty";
-    public static final String PUBLIC_KEY_USE = "use";
-    public static final String KEY_OPERATIONS = "key_ops";
-    public static final String KEY_ALGO = JwtConstants.HEADER_ALGORITHM;
-    public static final String KEY_ID = JwtConstants.HEADER_KEY_ID;
-    public static final String X509_URL = JwtConstants.HEADER_X509_URL;
-    public static final String X509_CHAIN = JwtConstants.HEADER_X509_CHAIN;
-    public static final String X509_THUMBPRINT = JwtConstants.HEADER_X509_THUMBPRINT;
-    public static final String X509_THUMBPRINT_SHA256 = JwtConstants.HEADER_X509_THUMBPRINT_SHA256;
-    
-    public static final String KEY_TYPE_OCTET = "oct";
-    public static final String KEY_TYPE_RSA = "RSA";
-    public static final String KEY_TYPE_ECURVE = "EC";
-    
-    public static final String PUBLIC_KEY_USE_SIGN = "sig";
-    public static final String PUBLIC_KEY_USE_ENCRYPT = "enc";
-    
-    public static final String KEY_OPER_SIGN = "sign";
-    public static final String KEY_OPER_VERIFY = "verify";
-    public static final String KEY_OPER_ENCRYPT = "encrypt";
-    public static final String KEY_OPER_DECRYPT = "decrypt";
-    
-    public JsonWebKey() {
-        
-    }
-    
-    public JsonWebKey(Map<String, Object> values) {
-        super(values);
-    }
-    
-    public void setKeyType(String keyType) {
-        super.setValue(KEY_TYPE, keyType);
-    }
-
-    public String getKeyType() {
-        return (String)super.getValue(KEY_TYPE);
-    }
-
-    public void setPublicKeyUse(String use) {
-        super.setValue(PUBLIC_KEY_USE, use);
-    }
-    
-    public String getPublicKeyUse() {
-        return (String)super.getValue(PUBLIC_KEY_USE);
-    }
-
-    public void setKeyOperation(List<String> keyOperation) {
-        super.setValue(KEY_OPERATIONS, keyOperation);
-    }
-
-    public List<String> getKeyOperation() {
-        return CastUtils.cast((List<?>)super.getValue(KEY_OPERATIONS));
-    }
-    
-    public void setAlgorithm(String algorithm) {
-        super.setValue(KEY_ALGO, algorithm);
-    }
-
-    public String getAlgorithm() {
-        return (String)super.getValue(KEY_ALGO);
-    }
-    
-    public void setKid(String kid) {
-        super.setValue(KEY_ID, kid);
-    }
-
-    public String getKid() {
-        return (String)super.getValue(KEY_ID);
-    }
-    
-    public void setX509Url(String x509Url) {
-        super.setValue(X509_URL, x509Url);
-    }
-    
-    public String getX509Url() {
-        return (String)super.getValue(X509_URL);
-    }
-
-    public void setX509Chain(String x509Chain) {
-        super.setValue(X509_CHAIN, x509Chain);
-    }
-
-    public String getX509Chain() {
-        return (String)super.getValue(X509_CHAIN);
-    }
-    
-    public void setX509Thumbprint(String x509Thumbprint) {
-        super.setValue(X509_THUMBPRINT, x509Thumbprint);
-    }
-    
-    public String getX509Thumbprint() {
-        return (String)super.getValue(X509_THUMBPRINT);
-    }
-    
-    public void setX509ThumbprintSHA256(String x509Thumbprint) {
-        super.setValue(X509_THUMBPRINT_SHA256, x509Thumbprint);
-    }
-    
-    public String getX509ThumbprintSHA256() {
-        return (String)super.getValue(X509_THUMBPRINT_SHA256);
-    }
-    
-    public JsonWebKey setProperty(String name, Object value) {
-        super.setValue(name, value);
-        return this;
-    }
-    
-    public Object getProperty(String name) {
-        return super.getValue(name);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyTest.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyTest.java
new file mode 100644
index 0000000..0505f64
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKeyTest.java
@@ -0,0 +1,171 @@
+/**
+ * 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.oauth2.jwk;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.rs.security.oauth2.jwt.JwtConstants;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JsonWebKeyTest extends Assert {
+    private static final String RSA_MODULUS_VALUE = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt"
+        + "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf"
+        + "0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt"
+        + "-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw";
+    private static final String RSA_PUBLIC_EXP_VALUE = "AQAB";
+    private static final String RSA_PRIVATE_EXP_VALUE = "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7d"
+        + "x5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ4"
+        + "6pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66"
+        + "jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q";
+    private static final String RSA_FIRST_PRIME_FACTOR_VALUE = "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQ"
+        + "BQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9"
+        + "RzzOGVQzXvNEvn7O0nVbfs";
+    private static final String RSA_SECOND_PRIME_FACTOR_VALUE = "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3"
+        + "vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfA"
+        + "ITAG9LUnADun4vIcb6yelxk";
+    private static final String RSA_FIRST_PRIME_CRT_VALUE = "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0o"
+        + "imYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUm"
+        + "s6rY3Ob8YeiKkTiBj0";
+    private static final String RSA_SECOND_PRIME_CRT_VALUE = "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6hu"
+        + "UUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvW"
+        + "rX-L18txXw494Q_cgk";
+    private static final String RSA_FIRST_CRT_COEFFICIENT_VALUE = "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfm"
+        + "t0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKF"
+        + "YItdldUKGzO6Ia6zTKhAVRU";
+    private static final String RSA_KID_VALUE = "2011-04-29";
+    private static final String EC_CURVE_VALUE = JsonWebKey.EC_CURVE_P256;
+    private static final String EC_X_COORDINATE_VALUE = "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4";
+    private static final String EC_Y_COORDINATE_VALUE = "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM";
+    private static final String EC_PRIVATE_KEY_VALUE = "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE";
+    private static final String EC_KID_VALUE = "1";
+    private static final String AES_SECRET_VALUE = "GawgguFyGrWKav7AX4VKUg";
+    private static final String AES_KID_VALUE = "AesWrapKey";
+    private static final String HMAC_SECRET_VALUE = "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3"
+        + "Yj0iPS4hcgUuTwjAzZr1Z9CAow";
+    private static final String HMAC_KID_VALUE = "HMACKey";
+    
+    @Test
+    public void testPublicSetAsList() throws Exception {
+        JsonWebKeys jwks = readKeySet("jwkPublicSet.txt");
+        List<JsonWebKey> keys = jwks.getKeys();
+        assertEquals(2, keys.size());
+        
+        JsonWebKey ecKey = keys.get(0);
+        assertEquals(6, ecKey.asMap().size());
+        validatePublicEcKey(ecKey);
+        JsonWebKey rsaKey = keys.get(1);
+        assertEquals(5, rsaKey.asMap().size());
+        validatePublicRsaKey(rsaKey);
+    }
+    
+    @Test
+    public void testPublicSetAsMap() throws Exception {
+        JsonWebKeys jwks = readKeySet("jwkPublicSet.txt");
+        Map<String, JsonWebKey> keysMap = jwks.getKeysMap();
+        assertEquals(2, keysMap.size());
+        
+        JsonWebKey rsaKey = keysMap.get(RSA_KID_VALUE);
+        assertEquals(5, rsaKey.asMap().size());
+        validatePublicRsaKey(rsaKey);
+        JsonWebKey ecKey = keysMap.get(EC_KID_VALUE);
+        assertEquals(6, ecKey.asMap().size());
+        validatePublicEcKey(ecKey);
+    }
+    
+    @Test
+    public void testPrivateSetAsList() throws Exception {
+        JsonWebKeys jwks = readKeySet("jwkPrivateSet.txt");
+        List<JsonWebKey> keys = jwks.getKeys();
+        assertEquals(2, keys.size());
+        
+        JsonWebKey ecKey = keys.get(0);
+        assertEquals(7, ecKey.asMap().size());
+        validatePrivateEcKey(ecKey);
+        JsonWebKey rsaKey = keys.get(1);
+        assertEquals(11, rsaKey.asMap().size());
+        validatePrivateRsaKey(rsaKey);
+    }
+    
+    @Test
+    public void testSecretSetAsList() throws Exception {
+        JsonWebKeys jwks = readKeySet("jwkSecretSet.txt");
+        List<JsonWebKey> keys = jwks.getKeys();
+        assertEquals(2, keys.size());
+        JsonWebKey aesKey = keys.get(0);
+        assertEquals(4, aesKey.asMap().size());
+        validateSecretAesKey(aesKey);
+        JsonWebKey hmacKey = keys.get(1);
+        assertEquals(4, hmacKey.asMap().size());
+        validateSecretHmacKey(hmacKey);
+    }
+    
+    private void validateSecretAesKey(JsonWebKey key) {
+        assertEquals(AES_SECRET_VALUE, key.getProperty(JsonWebKey.OCTET_KEY_VALUE));
+        assertEquals(AES_KID_VALUE, key.getKid());
+        assertEquals(JsonWebKey.KEY_TYPE_OCTET, key.getKeyType());
+        assertEquals(JwtConstants.A128KW_ALGO, key.getAlgorithm());
+    }
+    private void validateSecretHmacKey(JsonWebKey key) {
+        assertEquals(HMAC_SECRET_VALUE, key.getProperty(JsonWebKey.OCTET_KEY_VALUE));
+        assertEquals(HMAC_KID_VALUE, key.getKid());
+        assertEquals(JsonWebKey.KEY_TYPE_OCTET, key.getKeyType());
+        assertEquals(JwtConstants.HMAC_SHA_256_ALGO, key.getAlgorithm());
+    }
+    
+    private void validatePublicRsaKey(JsonWebKey key) {
+        assertEquals(RSA_MODULUS_VALUE, key.getProperty(JsonWebKey.RSA_MODULUS));
+        assertEquals(RSA_PUBLIC_EXP_VALUE, key.getProperty(JsonWebKey.RSA_PUBLIC_EXP));
+        assertEquals(RSA_KID_VALUE, key.getKid());
+        assertEquals(JsonWebKey.KEY_TYPE_RSA, key.getKeyType());
+        assertEquals(JwtConstants.RS_SHA_256_ALGO, key.getAlgorithm());
+    }
+    private void validatePrivateRsaKey(JsonWebKey key) {
+        validatePublicRsaKey(key);
+        assertEquals(RSA_PRIVATE_EXP_VALUE, key.getProperty(JsonWebKey.RSA_PRIVATE_EXP));
+        assertEquals(RSA_FIRST_PRIME_FACTOR_VALUE, key.getProperty(JsonWebKey.RSA_FIRST_PRIME_FACTOR));
+        assertEquals(RSA_SECOND_PRIME_FACTOR_VALUE, key.getProperty(JsonWebKey.RSA_SECOND_PRIME_FACTOR));
+        assertEquals(RSA_FIRST_PRIME_CRT_VALUE, key.getProperty(JsonWebKey.RSA_FIRST_PRIME_CRT));
+        assertEquals(RSA_SECOND_PRIME_CRT_VALUE, key.getProperty(JsonWebKey.RSA_SECOND_PRIME_CRT));
+        assertEquals(RSA_FIRST_CRT_COEFFICIENT_VALUE, key.getProperty(JsonWebKey.RSA_FIRST_CRT_COEFFICIENT));
+    }
+    private void validatePublicEcKey(JsonWebKey key) {
+        assertEquals(EC_X_COORDINATE_VALUE, key.getProperty(JsonWebKey.EC_X_COORDINATE));
+        assertEquals(EC_Y_COORDINATE_VALUE, key.getProperty(JsonWebKey.EC_Y_COORDINATE));
+        assertEquals(EC_KID_VALUE, key.getKid());
+        assertEquals(JsonWebKey.KEY_TYPE_ELLIPTIC, key.getKeyType());
+        assertEquals(EC_CURVE_VALUE, key.getProperty(JsonWebKey.EC_CURVE));
+        assertEquals(JsonWebKey.PUBLIC_KEY_USE_ENCRYPT, key.getPublicKeyUse());
+    }
+    private void validatePrivateEcKey(JsonWebKey key) {
+        validatePublicEcKey(key);
+        assertEquals(EC_PRIVATE_KEY_VALUE, key.getProperty(JsonWebKey.EC_PRIVATE_KEY));
+    }
+
+    public JsonWebKeys readKeySet(String fileName) throws Exception {
+        InputStream is = JsonWebKeyTest.class.getResourceAsStream(fileName);
+        String s = IOUtils.readStringFromStream(is);
+        JsonWebKeyReaderWriter reader = new JsonWebKeyReaderWriter();
+        return reader.jsonToJwks(s);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPrivateSet.txt
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPrivateSet.txt b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPrivateSet.txt
new file mode 100644
index 0000000..cb30c04
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPrivateSet.txt
@@ -0,0 +1,23 @@
+{"keys":
+       [
+         {"kty":"EC",
+          "crv":"P-256",
+          "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
+          "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
+          "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
+          "use":"enc",
+          "kid":"1"},
+
+         {"kty":"RSA",
+          "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+          "e":"AQAB",
+          "d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
+          "p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
+          "q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
+          "dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
+          "dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
+          "qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
+          "alg":"RS256",
+          "kid":"2011-04-29"}
+       ]
+     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPublicSet.txt
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPublicSet.txt b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPublicSet.txt
new file mode 100644
index 0000000..5a4a839
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkPublicSet.txt
@@ -0,0 +1,17 @@
+{"keys":
+       [
+         {"kty":"EC",
+          "crv":"P-256",
+          "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
+          "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
+          "use":"enc",
+          "kid":"1"},
+
+         {"kty":"RSA",
+          "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+          "e":"AQAB",
+          "alg":"RS256",
+          "kid":"2011-04-29"}
+          
+       ]
+     }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkSecretSet.txt
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkSecretSet.txt b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkSecretSet.txt
new file mode 100644
index 0000000..6520c75
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwk/jwkSecretSet.txt
@@ -0,0 +1,13 @@
+{"keys":
+       [
+         {"kty":"oct",
+          "alg":"A128KW",
+          "k":"GawgguFyGrWKav7AX4VKUg",
+          "kid":"AesWrapKey"},
+
+         {"kty":"oct",
+          "alg":"HS256",
+          "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow",
+          "kid":"HMACKey"}
+       ]
+     }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/e6df0172/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactReaderWriterTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactReaderWriterTest.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactReaderWriterTest.java
index 026575a..36c6aee 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactReaderWriterTest.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactReaderWriterTest.java
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.cxf.rs.security.oauth2.jwk.JsonWebKey;
 import org.apache.cxf.rs.security.oauth2.jwt.Algorithm;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtClaims;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtConstants;
@@ -34,7 +35,6 @@ import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtToken;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenReaderWriter;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenWriter;
-import org.apache.cxf.rs.security.oauth2.jwt.jwk.JsonWebKey;
 import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
 
 import org.junit.Assert;


Mime
View raw message