You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2014/09/19 16:47:52 UTC
[07/10] Changing the oauth2-jwt source folder to oauth2-jose
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
new file mode 100644
index 0000000..fed7e1f
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
@@ -0,0 +1,62 @@
+/**
+ * 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.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.HmacUtils;
+
+public class HmacJwsSignatureVerifier implements JwsSignatureVerifier {
+ private byte[] key;
+ private AlgorithmParameterSpec hmacSpec;
+
+ public HmacJwsSignatureVerifier(byte[] key) {
+ this(key, null);
+ }
+ public HmacJwsSignatureVerifier(byte[] key, AlgorithmParameterSpec spec) {
+ this.key = key;
+ this.hmacSpec = spec;
+ }
+ public HmacJwsSignatureVerifier(String encodedKey) {
+ try {
+ this.key = Base64UrlUtility.decode(encodedKey);
+ } catch (Base64Exception ex) {
+ throw new SecurityException();
+ }
+ }
+
+ @Override
+ public boolean verify(JwtHeaders headers, String unsignedText, byte[] signature) {
+ byte[] expected = computeMac(headers, unsignedText);
+ return Arrays.equals(expected, signature);
+ }
+
+ private byte[] computeMac(JwtHeaders headers, String text) {
+ return HmacUtils.computeHmac(key,
+ Algorithm.toJavaName(headers.getAlgorithm()),
+ hmacSpec,
+ text);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
new file mode 100644
index 0000000..422473f
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
@@ -0,0 +1,122 @@
+/**
+ * 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.UnsupportedEncodingException;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReader;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JwsCompactConsumer {
+ private JwtHeadersReader reader = new JwtTokenReaderWriter();
+ private String encodedSequence;
+ private String encodedSignature;
+ private String headersJson;
+ private String jwsPayload;
+ private JwsSignatureProperties props;
+ public JwsCompactConsumer(String encodedJws) {
+ this(encodedJws, null, null);
+ }
+ public JwsCompactConsumer(String encodedJws, JwsSignatureProperties props) {
+ this(encodedJws, props, null);
+ }
+ public JwsCompactConsumer(String encodedJws, JwtTokenReader r) {
+ this(encodedJws, null, r);
+ }
+ public JwsCompactConsumer(String encodedJws, JwsSignatureProperties props, JwtHeadersReader r) {
+ if (r != null) {
+ this.reader = r;
+ }
+ this.props = props;
+ String[] parts = encodedJws.split("\\.");
+ if (parts.length != 3) {
+ if (parts.length == 2 && encodedJws.endsWith(".")) {
+ encodedSignature = "";
+ } else {
+ throw new OAuthServiceException("Invalid JWS Compact sequence");
+ }
+ } else {
+ encodedSignature = parts[2];
+ }
+ headersJson = decodeToString(parts[0]);
+ jwsPayload = decodeToString(parts[1]);
+ encodedSequence = parts[0] + "." + parts[1];
+
+ }
+ public String getUnsignedEncodedPayload() {
+ return encodedSequence;
+ }
+ public String getEncodedSignature() {
+ return encodedSignature;
+ }
+ public String getDecodedJsonHeaders() {
+ return headersJson;
+ }
+ public String getDecodedJwsPayload() {
+ return jwsPayload;
+ }
+ public byte[] getDecodedJwsPayloadBytes() {
+ try {
+ return jwsPayload.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+ public byte[] getDecodedSignature() {
+ return encodedSignature.isEmpty() ? new byte[]{} : decode(encodedSignature);
+ }
+ public JwtHeaders getJwtHeaders() {
+ return getReader().fromJsonHeaders(headersJson);
+ }
+ public boolean verifySignatureWith(JwsSignatureVerifier validator) {
+ enforceJweSignatureProperties();
+ if (!validator.verify(getJwtHeaders(), getUnsignedEncodedPayload(), getDecodedSignature())) {
+ throw new SecurityException();
+ }
+ return true;
+ }
+ private void enforceJweSignatureProperties() {
+ if (props != null) {
+ //TODO:
+ }
+ }
+ private static String decodeToString(String encoded) {
+ try {
+ return new String(decode(encoded), "UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ throw new SecurityException(ex);
+ }
+
+ }
+ protected JwtHeadersReader getReader() {
+ return reader;
+ }
+ private static byte[] decode(String encoded) {
+ try {
+ return Base64UrlUtility.decode(encoded);
+ } catch (Base64Exception ex) {
+ throw new SecurityException(ex);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
new file mode 100644
index 0000000..ef4dd52
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
@@ -0,0 +1,109 @@
+/**
+ * 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.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JwsCompactProducer {
+ private JwtHeadersWriter writer = new JwtTokenReaderWriter();
+ private JwtHeaders headers;
+ private String plainJwsPayload;
+ private String signature;
+ private String plainRep;
+
+ public JwsCompactProducer(String plainJwsPayload) {
+ this(null, null, plainJwsPayload);
+ }
+ public JwsCompactProducer(JwtHeaders headers, String plainJwsPayload) {
+ this(headers, null, plainJwsPayload);
+ }
+ public JwsCompactProducer(JwtHeaders headers, JwtHeadersWriter w, String plainJwsPayload) {
+ this.headers = headers;
+ if (w != null) {
+ this.writer = w;
+ }
+ this.plainJwsPayload = plainJwsPayload;
+ }
+ public JwtHeaders getHeaders() {
+ if (headers == null) {
+ headers = new JwtHeaders();
+ }
+ return headers;
+ }
+ public String getUnsignedEncodedJws() {
+ checkAlgorithm();
+ if (plainRep == null) {
+ plainRep = Base64UrlUtility.encode(writer.headersToJson(getHeaders()))
+ + "."
+ + Base64UrlUtility.encode(plainJwsPayload);
+ }
+ return plainRep;
+ }
+
+ public String getSignedEncodedJws() {
+ checkAlgorithm();
+ boolean noSignature = StringUtils.isEmpty(signature);
+ if (noSignature && !isPlainText()) {
+ throw new IllegalStateException("Signature is not available");
+ }
+ return getUnsignedEncodedJws() + "." + (noSignature ? "" : signature);
+ }
+
+ public String signWith(JwsSignatureProvider signer) {
+ JwsSignature worker = signer.createJwsSignature(getHeaders());
+ try {
+ byte[] bytes = getUnsignedEncodedJws().getBytes("UTF-8");
+ worker.update(bytes, 0, bytes.length);
+ signWith(worker.sign());
+ return getSignedEncodedJws();
+ } catch (Exception ex) {
+ throw new SecurityException();
+ }
+ }
+
+ public String signWith(String signatureText) {
+ setEncodedSignature(Base64UrlUtility.encode(signatureText));
+ return getSignedEncodedJws();
+ }
+
+ public String signWith(byte[] signatureOctets) {
+ setEncodedSignature(Base64UrlUtility.encode(signatureOctets));
+ return getSignedEncodedJws();
+ }
+
+ private void setEncodedSignature(String sig) {
+ this.signature = sig;
+ }
+ private boolean isPlainText() {
+ return JwtConstants.PLAIN_TEXT_ALGO.equals(getAlgorithm());
+ }
+ private String getAlgorithm() {
+ return getHeaders().getAlgorithm();
+ }
+ private void checkAlgorithm() {
+ if (getAlgorithm() == null) {
+ throw new IllegalStateException("Algorithm header is not set");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.java
new file mode 100644
index 0000000..e395dc7
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactConsumer.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.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenJson;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReader;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+
+public class JwsJwtCompactConsumer extends JwsCompactConsumer {
+ private JwtToken token;
+ public JwsJwtCompactConsumer(String encodedJws) {
+ this(encodedJws, null, null);
+ }
+ public JwsJwtCompactConsumer(String encodedJws, JwsSignatureProperties props) {
+ this(encodedJws, props, null);
+ }
+ public JwsJwtCompactConsumer(String encodedJws, JwtTokenReader r) {
+ this(encodedJws, null, r);
+ }
+ public JwsJwtCompactConsumer(String encodedJws, JwsSignatureProperties props, JwtTokenReader r) {
+ super(encodedJws, props, r == null ? new JwtTokenReaderWriter() : r);
+ }
+ public JwtTokenJson getDecodedJsonToken() {
+ return new JwtTokenJson(getDecodedJsonHeaders(), getDecodedJwsPayload());
+ }
+ public JwtClaims getJwtClaims() {
+ return getJwtToken().getClaims();
+ }
+ public JwtToken getJwtToken() {
+ if (token == null) {
+ token = ((JwtTokenReaderWriter)getReader()).fromJson(
+ new JwtTokenJson(getDecodedJsonHeaders(), getDecodedJwsPayload()));
+ }
+ return token;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
new file mode 100644
index 0000000..cc227af
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJwtCompactProducer.java
@@ -0,0 +1,51 @@
+/**
+ * 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.JwtHeaders;
+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.JwtTokenWriter;
+
+public class JwsJwtCompactProducer extends JwsCompactProducer {
+
+ public JwsJwtCompactProducer(JwtToken token) {
+ this(token, null);
+ }
+ public JwsJwtCompactProducer(JwtClaims claims) {
+ this(new JwtToken(null, claims), null);
+ }
+ public JwsJwtCompactProducer(JwtHeaders headers, JwtClaims claims) {
+ this(headers, claims, null);
+ }
+ public JwsJwtCompactProducer(JwtHeaders headers, JwtClaims claims, JwtTokenWriter w) {
+ this(new JwtToken(headers, claims), w);
+ }
+ public JwsJwtCompactProducer(JwtToken token, JwtTokenWriter w) {
+ super(token.getHeaders(), w, serializeClaims(token.getClaims(), w));
+ }
+
+ private static String serializeClaims(JwtClaims claims, JwtTokenWriter writer) {
+ if (writer == null) {
+ writer = new JwtTokenReaderWriter();
+ }
+ return writer.claimsToJson(claims);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
new file mode 100644
index 0000000..bfb093f
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsOutputStream.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.cxf.rs.security.oauth2.utils.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 {
+ try {
+ signature.update(b, off, len);
+ } catch (Throwable ex) {
+ throw new SecurityException();
+ }
+ out.write(b, off, len);
+ }
+ @Override
+ public void flush() throws IOException {
+ if (flushed) {
+ return;
+ }
+ try {
+ byte[] finalBytes = signature.sign();
+ out.write(new byte[]{'.'});
+ Base64UrlUtility.encodeAndStream(finalBytes, 0, finalBytes.length, out);
+ } catch (Exception ex) {
+ throw new SecurityException();
+ }
+ flushed = true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignature.java b/rt/rs/security/oauth-parent/oauth2-jose/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/oauth-parent/oauth2-jose/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/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProperties.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProperties.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProperties.java
new file mode 100644
index 0000000..e07f559
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProperties.java
@@ -0,0 +1,23 @@
+/**
+ * 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 class JwsSignatureProperties {
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.java
new file mode 100644
index 0000000..a4d12bf
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureProvider.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.jwt.JwtHeaders;
+
+public interface JwsSignatureProvider {
+ String getAlgorithm();
+ JwsSignature createJwsSignature(JwtHeaders headers);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.java
new file mode 100644
index 0000000..ea4a01f
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsSignatureVerifier.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;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+
+public interface JwsSignatureVerifier {
+ boolean verify(JwtHeaders headers, String unsignedText, byte[] signature);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
new file mode 100644
index 0000000..20b2672
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
@@ -0,0 +1,64 @@
+/**
+ * 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.Algorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
+
+public final class JwsUtils {
+ private JwsUtils() {
+
+ }
+ public static JwsSignatureProvider getSignatureProvider(JsonWebKey jwk) {
+ return getSignatureProvider(jwk, null);
+ }
+ public static JwsSignatureProvider getSignatureProvider(JsonWebKey jwk, String defaultAlgorithm) {
+ String rsaSignatureAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm();
+ JwsSignatureProvider theSigProvider = null;
+ if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) {
+ theSigProvider = new PrivateKeyJwsSignatureProvider(JwkUtils.toRSAPrivateKey(jwk),
+ rsaSignatureAlgo);
+ } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())
+ && Algorithm.isHmacSign(rsaSignatureAlgo)) {
+ theSigProvider =
+ new HmacJwsSignatureProvider((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE),
+ rsaSignatureAlgo);
+ } else if (JsonWebKey.KEY_TYPE_ELLIPTIC.equals(jwk.getKeyType())) {
+ theSigProvider = new EcDsaJwsSignatureProvider(JwkUtils.toECPrivateKey(jwk),
+ rsaSignatureAlgo);
+ }
+ return theSigProvider;
+ }
+ public static JwsSignatureVerifier getSignatureVerifier(JsonWebKey jwk, String defaultAlgorithm) {
+ String rsaSignatureAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm();
+ JwsSignatureVerifier theVerifier = null;
+ if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) {
+ theVerifier = new PublicKeyJwsSignatureVerifier(JwkUtils.toRSAPublicKey(jwk));
+ } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())
+ && Algorithm.isHmacSign(rsaSignatureAlgo)) {
+ theVerifier =
+ new HmacJwsSignatureVerifier((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE));
+ } else if (JsonWebKey.KEY_TYPE_ELLIPTIC.equals(jwk.getKeyType())) {
+ theVerifier = new PublicKeyJwsSignatureVerifier(JwkUtils.toECPublicKey(jwk));
+ }
+ return theVerifier;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
new file mode 100644
index 0000000..bbd92aa
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+
+public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider {
+ private static final Set<String> SUPPORTED_ALGORITHMS = new HashSet<String>(
+ Arrays.asList(Algorithm.SHA256withRSA.getJwtName(),
+ Algorithm.SHA384withRSA.getJwtName(),
+ Algorithm.SHA512withRSA.getJwtName()));
+ private PrivateKey key;
+ private SecureRandom random;
+ private AlgorithmParameterSpec signatureSpec;
+
+ public PrivateKeyJwsSignatureProvider(PrivateKey key, String algo) {
+ this(key, null, algo);
+ }
+ public PrivateKeyJwsSignatureProvider(PrivateKey key, AlgorithmParameterSpec spec, String algo) {
+ this(key, null, spec, algo);
+ }
+ public PrivateKeyJwsSignatureProvider(PrivateKey key, SecureRandom random,
+ AlgorithmParameterSpec spec, String algo) {
+ this(key, random, spec, SUPPORTED_ALGORITHMS, algo);
+ }
+ protected PrivateKeyJwsSignatureProvider(PrivateKey key,
+ SecureRandom random,
+ AlgorithmParameterSpec spec,
+ Set<String> supportedAlgorithms,
+ String algo) {
+ super(supportedAlgorithms, algo);
+ this.key = key;
+ this.random = random;
+ this.signatureSpec = spec;
+ }
+ protected JwsSignature doCreateJwsSignature(JwtHeaders headers) {
+ final Signature s = CryptoUtils.getSignature(key,
+ Algorithm.toJavaName(headers.getAlgorithm()),
+ random,
+ signatureSpec);
+ return new JwsSignature() {
+
+ @Override
+ public void update(byte[] src, int off, int len) {
+ try {
+ s.update(src, off, len);
+ } catch (SignatureException ex) {
+ throw new SecurityException();
+ }
+ }
+
+ @Override
+ public byte[] sign() {
+ try {
+ return s.sign();
+ } catch (SignatureException ex) {
+ throw new SecurityException();
+ }
+ }
+
+ };
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java
new file mode 100644
index 0000000..c4748e0
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+
+public class PublicKeyJwsSignatureVerifier implements JwsSignatureVerifier {
+ private PublicKey key;
+ private AlgorithmParameterSpec signatureSpec;
+ public PublicKeyJwsSignatureVerifier(PublicKey key) {
+ this(key, null);
+ }
+ public PublicKeyJwsSignatureVerifier(PublicKey key, AlgorithmParameterSpec spec) {
+ this.key = key;
+ this.signatureSpec = spec;
+ }
+ @Override
+ public boolean verify(JwtHeaders headers, String unsignedText, byte[] signature) {
+ try {
+ return CryptoUtils.verifySignature(unsignedText.getBytes("UTF-8"),
+ signature,
+ key,
+ Algorithm.toJavaName(headers.getAlgorithm()),
+ signatureSpec);
+ } catch (Exception ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObject.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObject.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObject.java
new file mode 100644
index 0000000..e8d45e5
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObject.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.rs.security.jose.jwt;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public abstract class AbstractJwtObject {
+ protected Map<String, Object> values = new LinkedHashMap<String, Object>();
+
+ protected AbstractJwtObject() {
+
+ }
+
+ protected AbstractJwtObject(Map<String, Object> values) {
+ this.values = values;
+ }
+
+ protected void setValue(String name, Object value) {
+ values.put(name, value);
+ }
+
+ protected Object getValue(String name) {
+ return values.get(name);
+ }
+
+ public Map<String, Object> asMap() {
+ return new LinkedHashMap<String, Object>(values);
+ }
+
+ protected Long getLongDate(String name) {
+ Object object = getValue(name);
+ return object instanceof Long ? (Long)object : Long.valueOf(object.toString());
+ }
+
+ public int hashCode() {
+ return values.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ return obj instanceof AbstractJwtObject && ((AbstractJwtObject)obj).values.equals(this.values);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObjectReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObjectReaderWriter.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJwtObjectReaderWriter.java
new file mode 100644
index 0000000..a70eca7
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/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.jose.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/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.java
new file mode 100644
index 0000000..46644a8
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtClaims.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.jwt;
+
+import java.util.Map;
+
+
+
+
+public class JwtClaims extends AbstractJwtObject {
+
+ 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)getValue(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 getLongDate(JwtConstants.CLAIM_EXPIRY);
+ }
+
+ public void setNotBefore(Long notBefore) {
+ setClaim(JwtConstants.CLAIM_NOT_BEFORE, notBefore);
+ }
+
+ public Long getNotBefore() {
+ return getLongDate(JwtConstants.CLAIM_NOT_BEFORE);
+ }
+
+ public void setIssuedAt(Long issuedAt) {
+ setClaim(JwtConstants.CLAIM_ISSUED_AT, issuedAt);
+ }
+
+ public Long getIssuedAt() {
+ return getLongDate(JwtConstants.CLAIM_ISSUED_AT);
+ }
+
+ public void setTokenId(String id) {
+ setValue(JwtConstants.CLAIM_JWT_ID, id);
+ }
+
+ public String getTokenId() {
+ return (String)getClaim(JwtConstants.CLAIM_JWT_ID);
+ }
+
+ public JwtClaims setClaim(String name, Object value) {
+ setValue(name, value);
+ return this;
+ }
+
+ public Object getClaim(String name) {
+ return getValue(name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
new file mode 100644
index 0000000..e912b31
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtConstants.java
@@ -0,0 +1,89 @@
+/**
+ * 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 HEADER_TYPE = "typ";
+ public static final String HEADER_ALGORITHM = "alg";
+ public static final String HEADER_CONTENT_TYPE = "cty";
+ public static final String HEADER_CRITICAL = "crit";
+
+ public static final String HEADER_KEY_ID = "kid";
+ public static final String HEADER_X509_URL = "x5u";
+ public static final String HEADER_X509_CHAIN = "x5c";
+ public static final String HEADER_X509_THUMBPRINT = "x5t";
+ public static final String HEADER_X509_THUMBPRINT_SHA256 = "x5t#S256";
+ public static final String HEADER_JSON_WEB_KEY = "jwk";
+ public static final String HEADER_JSON_WEB_KEY_SET = "jku";
+
+ public static final String JWE_HEADER_KEY_ENC_ALGORITHM = HEADER_ALGORITHM;
+ public static final String JWE_HEADER_CONTENT_ENC_ALGORITHM = "enc";
+ public static final String JWE_HEADER_ZIP_ALGORITHM = "zip";
+ public static final String DEFLATE_ZIP_ALGORITHM = "DEF";
+
+ public static final String TYPE_JWT = "JWT";
+ public static final String TYPE_JOSE = "JOSE";
+ public static final String TYPE_JOSE_JSON = "JOSE+JSON";
+ public static final String MEDIA_TYPE_JOSE_JSON = "application/jose+json";
+
+ public static final String 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 PLAIN_TEXT_ALGO = "none";
+ public static final String HMAC_SHA_256_ALGO = "HS256";
+ public static final String HMAC_SHA_384_ALGO = "HS384";
+ public static final String HMAC_SHA_512_ALGO = "HS512";
+ public static final String RS_SHA_256_ALGO = "RS256";
+ public static final String RS_SHA_384_ALGO = "RS384";
+ public static final String RS_SHA_512_ALGO = "RS512";
+ public static final String ES_SHA_256_ALGO = "ES256";
+ public static final String ES_SHA_384_ALGO = "ES384";
+ public static final String ES_SHA_512_ALGO = "ES512";
+
+ // Key Encryption
+ public static final String RSA_OAEP_ALGO = "RSA-OAEP";
+ public static final String RSA_OAEP_256_ALGO = "RSA-OAEP-256";
+ public static final String RSA_1_5_ALGO = "RSA1_5";
+ public static final String A128KW_ALGO = "A128KW";
+ public static final String A192KW_ALGO = "A192KW";
+ public static final String A256KW_ALGO = "A256KW";
+ public static final String A128GCMKW_ALGO = "A128GCMKW";
+ public static final String A192GCMKW_ALGO = "A192GCMKW";
+ public static final String A256GCMKW_ALGO = "A256GCMKW";
+ public static final String PBES2_HS256_A128KW_ALGO = "PBES2-HS256+A128KW";
+ public static final String PBES2_HS384_A192KW_ALGO = "PBES2-HS384+A192KW";
+ public static final String PBES2_HS512_A256KW_ALGO = "PBES2-HS512+A256KW";
+ // Content Encryption
+ public static final String A128CBC_HS256_ALGO = "A128CBC-HS256";
+ public static final String A192CBC_HS384_ALGO = "A192CBC-HS384";
+ public static final String A256CBC_HS512_ALGO = "A256CBC-HS512";
+ public static final String A128GCM_ALGO = "A128GCM";
+ public static final String A192GCM_ALGO = "A192GCM";
+ public static final String A256GCM_ALGO = "A256GCM";
+
+ private JwtConstants() {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeaders.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeaders.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeaders.java
new file mode 100644
index 0000000..b723f7d
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeaders.java
@@ -0,0 +1,172 @@
+/**
+ * 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.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JwtHeaders extends AbstractJwtObject {
+
+ public JwtHeaders() {
+ }
+
+ public JwtHeaders(String algorithm) {
+ init(algorithm);
+ }
+
+ public JwtHeaders(Algorithm algo) {
+ init(algo.getJwtName());
+ }
+
+ public JwtHeaders(Map<String, Object> values) {
+ super(values);
+ }
+
+ private void init(String algo) {
+ setType(JwtConstants.TYPE_JWT);
+ this.setAlgorithm(algo);
+ }
+
+
+ public void setType(String type) {
+ setHeader(JwtConstants.HEADER_TYPE, type);
+ }
+
+ public String getType() {
+ return (String)getHeader(JwtConstants.HEADER_TYPE);
+ }
+
+ public void setContentType(String type) {
+ setHeader(JwtConstants.HEADER_CONTENT_TYPE, type);
+ }
+
+ public String getContentType() {
+ return (String)getHeader(JwtConstants.HEADER_CONTENT_TYPE);
+ }
+
+ public void setAlgorithm(String algo) {
+ setHeader(JwtConstants.HEADER_ALGORITHM, algo);
+ }
+
+ public String getAlgorithm() {
+ return (String)getHeader(JwtConstants.HEADER_ALGORITHM);
+ }
+
+ public void setKeyId(String kid) {
+ setHeader(JwtConstants.HEADER_KEY_ID, kid);
+ }
+
+ public String getKeyId() {
+ return (String)getHeader(JwtConstants.HEADER_KEY_ID);
+ }
+
+ public void setX509Url(String x509Url) {
+ setHeader(JwtConstants.HEADER_X509_URL, x509Url);
+ }
+
+ public String getX509Url() {
+ return (String)getHeader(JwtConstants.HEADER_X509_URL);
+ }
+
+ public void setX509Chain(String x509Chain) {
+ setHeader(JwtConstants.HEADER_X509_CHAIN, x509Chain);
+ }
+
+ public String getX509Chain() {
+ return (String)getHeader(JwtConstants.HEADER_X509_CHAIN);
+ }
+
+ public void setX509Thumbprint(String x509Thumbprint) {
+ setHeader(JwtConstants.HEADER_X509_THUMBPRINT, x509Thumbprint);
+ }
+
+ public String getX509Thumbprint() {
+ return (String)getHeader(JwtConstants.HEADER_X509_THUMBPRINT);
+ }
+
+ public void setX509ThumbprintSHA256(String x509Thumbprint) {
+ super.setValue(JwtConstants.HEADER_X509_THUMBPRINT_SHA256, x509Thumbprint);
+ }
+
+ public String getX509ThumbprintSHA256() {
+ return (String)super.getValue(JwtConstants.HEADER_X509_THUMBPRINT_SHA256);
+ }
+
+ public void setCritical(List<String> crit) {
+ setHeader(JwtConstants.HEADER_CRITICAL, crit);
+ }
+
+ public List<String> getCritical() {
+ return CastUtils.cast((List<?>)getHeader(JwtConstants.HEADER_CRITICAL));
+ }
+
+ public void setJsonWebKey(JsonWebKey key) {
+ setValue(JwtConstants.HEADER_JSON_WEB_KEY, key);
+ }
+
+ public JsonWebKey getJsonWebKey() {
+ Object jsonWebKey = getValue(JwtConstants.HEADER_JSON_WEB_KEY);
+ if (jsonWebKey == null || jsonWebKey instanceof JsonWebKey) {
+ return (JsonWebKey)jsonWebKey;
+ }
+ Map<String, Object> map = CastUtils.cast((Map<?, ?>)jsonWebKey);
+ return new JsonWebKey(map);
+ }
+
+ public JwtHeaders setHeader(String name, Object value) {
+ setValue(name, value);
+ return this;
+ }
+
+ public Object getHeader(String name) {
+ return getValue(name);
+ }
+
+ public JwtHeaders setIntegerHeader(String name, Integer value) {
+ setValue(name, value);
+ return this;
+ }
+
+ public Integer getIntegerHeader(String name) {
+ Object value = getValue(name);
+ if (value != null) {
+ return value instanceof Integer ? (Integer)value : Integer.parseInt(value.toString());
+ } else {
+ return null;
+ }
+ }
+ public JwtHeaders setLongHeader(String name, Long value) {
+ setValue(name, value);
+ return this;
+ }
+
+ public Long getLongHeader(String name) {
+ Object value = getValue(name);
+ if (value != null) {
+ return value instanceof Long ? (Long)value : Long.parseLong(value.toString());
+ } else {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersReader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersReader.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersReader.java
new file mode 100644
index 0000000..8a15819
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersReader.java
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwt;
+
+
+public interface JwtHeadersReader {
+ JwtHeaders fromJsonHeaders(String jsonHeaders);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersWriter.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersWriter.java
new file mode 100644
index 0000000..6c63dea
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtHeadersWriter.java
@@ -0,0 +1,27 @@
+/**
+ * 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 interface JwtHeadersWriter {
+
+ String headersToJson(JwtHeaders headers);
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.java
new file mode 100644
index 0000000..630813c
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtToken.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.jose.jwt;
+
+
+
+public class JwtToken {
+ private JwtHeaders headers;
+ private JwtClaims claims;
+ public JwtToken(JwtHeaders headers, JwtClaims claims) {
+ this.headers = headers;
+ this.claims = claims;
+ }
+ public JwtHeaders getHeaders() {
+ return headers;
+ }
+ public JwtClaims getClaims() {
+ return claims;
+ }
+ 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/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenJson.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenJson.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenJson.java
new file mode 100644
index 0000000..e8e79f0
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenJson.java
@@ -0,0 +1,37 @@
+/**
+ * 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 class JwtTokenJson {
+ private String headersJson;
+ private String claimsJson;
+ public JwtTokenJson(String headersJson, String claimsJson) {
+ this.headersJson = headersJson;
+ this.claimsJson = claimsJson;
+ }
+ public String getHeadersJson() {
+ return headersJson;
+ }
+ public String getClaimsJson() {
+ return claimsJson;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReader.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReader.java
new file mode 100644
index 0000000..2be6305
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReader.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.jwt;
+
+
+public interface JwtTokenReader extends JwtHeadersReader {
+ JwtClaims fromJsonClaims(String jsonClaims);
+ JwtToken fromJson(JwtTokenJson jsonPair);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
new file mode 100644
index 0000000..c207e0e
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenReaderWriter.java
@@ -0,0 +1,67 @@
+/**
+ * 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 class JwtTokenReaderWriter extends AbstractJwtObjectReaderWriter
+ implements JwtTokenReader, JwtTokenWriter {
+ @Override
+ public String headersToJson(JwtHeaders headers) {
+ return toJson(headers);
+ }
+
+ @Override
+ public String claimsToJson(JwtClaims claims) {
+ return toJson(claims);
+ }
+
+ @Override
+ public JwtTokenJson tokenToJson(JwtToken token) {
+ return new JwtTokenJson(toJson(token.getHeaders()),
+ toJson(token.getClaims()));
+ }
+
+ @Override
+ public JwtHeaders fromJsonHeaders(String headersJson) {
+ JwtHeaders headers = new JwtHeaders();
+ fromJsonInternal(headers, headersJson);
+ return headers;
+ }
+
+ @Override
+ public JwtClaims fromJsonClaims(String claimsJson) {
+ JwtClaims claims = new JwtClaims();
+ fromJsonInternal(claims, claimsJson);
+ return claims;
+
+ }
+
+ private JwtToken fromJson(String headersJson, String claimsJson) {
+ JwtHeaders headers = fromJsonHeaders(headersJson);
+ JwtClaims claims = fromJsonClaims(claimsJson);
+ return new JwtToken(headers, claims);
+ }
+
+ @Override
+ public JwtToken fromJson(JwtTokenJson pair) {
+ return fromJson(pair.getHeadersJson(), pair.getClaimsJson());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenWriter.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenWriter.java
new file mode 100644
index 0000000..bdbd029
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtTokenWriter.java
@@ -0,0 +1,28 @@
+/**
+ * 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 interface JwtTokenWriter extends JwtHeadersWriter {
+
+ String claimsToJson(JwtClaims claims);
+ JwtTokenJson tokenToJson(JwtToken token);
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
new file mode 100644
index 0000000..6238e2f
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwt;
+
+public final class JwtUtils {
+ private JwtUtils() {
+
+ }
+
+ public static String checkContentType(String contentType, String defaultType) {
+ if (contentType != null) {
+ int paramIndex = contentType.indexOf(';');
+ String typeWithoutParams = paramIndex == -1 ? contentType : contentType.substring(0, paramIndex);
+ if (typeWithoutParams.indexOf('/') == -1) {
+ contentType = "application/" + contentType;
+ }
+ } else {
+ contentType = defaultType;
+ }
+ return contentType;
+ }
+ public static String expandContentType(String contentType) {
+ int paramIndex = contentType.indexOf(';');
+ String typeWithoutParams = paramIndex == -1 ? contentType : contentType.substring(0, paramIndex);
+ if (typeWithoutParams.indexOf('/') == -1) {
+ contentType = "application/" + contentType;
+ }
+ return contentType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java
new file mode 100644
index 0000000..4572b30
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtBearerGrant.java
@@ -0,0 +1,69 @@
+/**
+ * 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.grant;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+public abstract class AbstractJwtBearerGrant implements AccessTokenGrant {
+ private static final long serialVersionUID = 5754722119855372511L;
+ private String assertion;
+ private String scope;
+ private boolean encoded;
+ private String grantType;
+ protected AbstractJwtBearerGrant(String grantType, String assertion, boolean encoded, String scope) {
+ this.grantType = grantType;
+ this.assertion = assertion;
+ this.encoded = encoded;
+ this.scope = scope;
+ }
+
+ public String getType() {
+ return grantType;
+ }
+
+ protected MultivaluedMap<String, String> initMap() {
+ MultivaluedMap<String, String> map = new MetadataMap<String, String>();
+ map.putSingle(OAuthConstants.GRANT_TYPE, grantType);
+ return map;
+ }
+
+ protected void addScope(MultivaluedMap<String, String> map) {
+ if (scope != null) {
+ map.putSingle(OAuthConstants.SCOPE, scope);
+ }
+ }
+
+ protected String encodeAssertion() {
+ if (encoded) {
+ return assertion;
+ }
+
+ try {
+ return Base64UrlUtility.encode(assertion);
+ } catch (Exception ex) {
+ throw new OAuthServiceException(ex.getMessage(), ex);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/4640cf1e/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.java
new file mode 100644
index 0000000..dbc8ffe
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/grant/AbstractJwtHandler.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.jwt.grant;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+
+/**
+ * The "JWT Bearer" grant handler
+ */
+public abstract class AbstractJwtHandler extends AbstractGrantHandler {
+ private Set<String> supportedIssuers;
+ private JwsSignatureVerifier jwsVefifier;
+
+ protected AbstractJwtHandler(List<String> grants) {
+ super(grants);
+ }
+
+ protected void validateSignature(JwtHeaders headers, String unsignedText, byte[] signature) {
+ if (jwsVefifier.verify(headers, unsignedText, signature)) {
+ throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+ }
+ }
+
+ protected void validateClaims(Client client, JwtClaims claims) {
+ validateIssuer(claims.getIssuer());
+ validateSubject(client, claims.getSubject());
+ validateAudience(client, claims.getAudience());
+ validateExpiryTime(claims.getExpiryTime());
+ validateNotBeforeTime(claims.getNotBefore());
+ validateIssuedAtTime(claims.getIssuedAt());
+ validateTokenId(claims.getTokenId());
+ }
+
+ protected void validateIssuer(String issuer) {
+ if (issuer == null || !supportedIssuers.contains(issuer)) {
+ throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+ }
+ }
+
+ protected void validateSubject(Client client, String subject) {
+ //TODO
+ }
+ protected void validateAudience(Client client, String audience) {
+ //TODO
+ }
+ protected void validateExpiryTime(Long timestamp) {
+ if (timestamp != null) {
+ //TODO
+ }
+ }
+ protected void validateNotBeforeTime(Long timestamp) {
+ if (timestamp != null) {
+ //TODO
+ }
+ }
+ protected void validateIssuedAtTime(Long timestamp) {
+ if (timestamp != null) {
+ //TODO
+ }
+ }
+ protected void validateTokenId(String tokenId) {
+ if (tokenId != null) {
+ //TODO
+ }
+ }
+ public void setSupportedIssuers(Set<String> supportedIssuers) {
+ this.supportedIssuers = supportedIssuers;
+ }
+
+ public void setJwsVefifier(JwsSignatureVerifier jwsVefifier) {
+ this.jwsVefifier = jwsVefifier;
+ }
+
+}