Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id DA1A911C95 for ; Fri, 19 Sep 2014 14:47:47 +0000 (UTC) Received: (qmail 7847 invoked by uid 500); 19 Sep 2014 14:47:47 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 7698 invoked by uid 500); 19 Sep 2014 14:47:47 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 7300 invoked by uid 99); 19 Sep 2014 14:47:47 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Sep 2014 14:47:47 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3A88D8A5FCA; Fri, 19 Sep 2014 14:47:47 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Date: Fri, 19 Sep 2014 14:47:52 -0000 Message-Id: <6b736147d2db47fba49c2e985cbdee2e@git.apache.org> In-Reply-To: <3afbddcbfc49444cb08552f06a8a935f@git.apache.org> References: <3afbddcbfc49444cb08552f06a8a935f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [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 SUPPORTED_ALGORITHMS = new HashSet( + 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 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 values = new LinkedHashMap(); + + protected AbstractJwtObject() { + + } + + protected AbstractJwtObject(Map 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 asMap() { + return new LinkedHashMap(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 DATE_PROPERTIES = + new HashSet(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 map) { + sb.append("{"); + for (Iterator> it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry 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)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 values = readJwtObjectAsMap(theJson.substring(1, theJson.length() - 1)); + fromJsonInternal(jwt, values); + } + + protected void fromJsonInternal(AbstractJwtObject jwt, Map values) { + for (Map.Entry entry : values.entrySet()) { + jwt.setValue(entry.getKey(), entry.getValue()); + } + } + + protected Map readJwtObjectAsMap(String json) { + Map values = new LinkedHashMap(); + 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 readJwtObjectAsList(String json) { + List values = new LinkedList(); + 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 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 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 crit) { + setHeader(JwtConstants.HEADER_CRITICAL, crit); + } + + public List 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 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 initMap() { + MultivaluedMap map = new MetadataMap(); + map.putSingle(OAuthConstants.GRANT_TYPE, grantType); + return map; + } + + protected void addScope(MultivaluedMap 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 supportedIssuers; + private JwsSignatureVerifier jwsVefifier; + + protected AbstractJwtHandler(List 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 supportedIssuers) { + this.supportedIssuers = supportedIssuers; + } + + public void setJwsVefifier(JwsSignatureVerifier jwsVefifier) { + this.jwsVefifier = jwsVefifier; + } + +}