Repository: cxf Updated Branches: refs/heads/master ad9719178 -> 607f93599
Refactoring JAX-RS providers Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/607f9359 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/607f9359 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/607f9359 Branch: refs/heads/master Commit: 607f935994fcdb742b1607d3df2ce3d1b5c4dcf1 Parents: ad97191 Author: Sergey Beryozkin <[email protected]> Authored: Fri Jun 13 17:17:21 2014 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Fri Jun 13 17:17:21 2014 +0100 ---------------------------------------------------------------------- .../security/oauth2/jws/JwsCompactConsumer.java | 7 + .../cxf/rs/security/oauth2/jwt/JwtUtils.java | 36 +++++ .../jwt/jaxrs/AbstractJwsReaderProvider.java | 69 +++++++++ .../jwt/jaxrs/AbstractJwsWriterProvider.java | 72 +++++++++ .../jwt/jaxrs/JweClientResponseFilter.java | 4 +- .../jwt/jaxrs/JweContainerRequestFilter.java | 2 + .../oauth2/jwt/jaxrs/JweWriterInterceptor.java | 10 +- .../jwt/jaxrs/JwsClientResponseFilter.java | 51 ++++++ .../jwt/jaxrs/JwsContainerRequestFilter.java | 53 +++++++ .../jwt/jaxrs/JwsJwtMessageBodyReader.java | 55 +++++++ .../jwt/jaxrs/JwsJwtMessageBodyWriter.java | 54 +++++++ .../jwt/jaxrs/JwsMessageBodyProvider.java | 154 ------------------- .../oauth2/jwt/jaxrs/JwsWriterInterceptor.java | 48 ++++++ .../security/oauth2/jwt/jaxrs/Priorities.java | 31 ++++ .../oauth2/utils/crypto/CryptoUtils.java | 3 + 15 files changed, 488 insertions(+), 161 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactConsumer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactConsumer.java index 430d4cc..57c7c69 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactConsumer.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsCompactConsumer.java @@ -76,6 +76,13 @@ public class JwsCompactConsumer { 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); } http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtUtils.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtUtils.java new file mode 100644 index 0000000..c674453 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtUtils.java @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt; + +public final class JwtUtils { + private JwtUtils() { + + } + + public static String checkContentType(String contentType) { + if (contentType != null) { + 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/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsReaderProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsReaderProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsReaderProvider.java new file mode 100644 index 0000000..e03d5dc --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsReaderProvider.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.oauth2.jwt.jaxrs; + +import java.security.PublicKey; + +import org.apache.cxf.Bus; +import org.apache.cxf.endpoint.Endpoint; +import org.apache.cxf.jaxrs.utils.JAXRSUtils; +import org.apache.cxf.message.Message; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureProperties; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.oauth2.jws.PublicKeyJwsSignatureVerifier; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + +public class AbstractJwsReaderProvider { + private static final String RSSEC_SIGNATURE_PROPS = "rs-security.signature.properties"; + + private JwsSignatureVerifier sigVerifier; + private JwsSignatureProperties sigProperties; + + public void setSigVerifier(JwsSignatureVerifier sigVerifier) { + this.sigVerifier = sigVerifier; + } + + public void setSigProperties(JwsSignatureProperties sigProperties) { + this.sigProperties = sigProperties; + } + + public JwsSignatureProperties getSigProperties() { + return sigProperties; + } + + protected JwsSignatureVerifier getInitializedSigVerifier() { + if (sigVerifier != null) { + return sigVerifier; + } + Message m = JAXRSUtils.getCurrentMessage(); + if (m == null) { + return null; + } + String propLoc = (String)m.getContextualProperty(RSSEC_SIGNATURE_PROPS); + if (propLoc == null) { + return null; + } + + Bus bus = (Bus)m.getExchange().get(Endpoint.class).get(Bus.class.getName()); + PublicKey pk = CryptoUtils.loadPublicKey(propLoc, bus); + return new PublicKeyJwsSignatureVerifier(pk); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsWriterProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsWriterProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsWriterProvider.java new file mode 100644 index 0000000..b67d472 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJwsWriterProvider.java @@ -0,0 +1,72 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.PrivateKey; + +import org.apache.cxf.Bus; +import org.apache.cxf.endpoint.Endpoint; +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.jaxrs.utils.JAXRSUtils; +import org.apache.cxf.message.Message; +import org.apache.cxf.rs.security.oauth2.jws.JwsCompactProducer; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureProvider; +import org.apache.cxf.rs.security.oauth2.jws.PrivateKeyJwsSignatureProvider; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.PrivateKeyPasswordProvider; + +public class AbstractJwsWriterProvider { + private static final String RSSEC_SIGNATURE_PROPS = "rs-security.signature.properties"; + private static final String RSSEC_KEY_PSWD_PROVIDER = "org.apache.rs.security.crypto.private.provider"; + + private JwsSignatureProvider sigProvider; + + public void setSigProvider(JwsSignatureProvider sigProvider) { + this.sigProvider = sigProvider; + } + + + protected JwsSignatureProvider getInitializedSigProvider() { + if (sigProvider != null) { + return sigProvider; + } + Message m = JAXRSUtils.getCurrentMessage(); + if (m == null) { + throw new SecurityException(); + } + String propLoc = (String)m.getContextualProperty(RSSEC_SIGNATURE_PROPS); + if (propLoc == null) { + throw new SecurityException(); + } + + PrivateKeyPasswordProvider cb = (PrivateKeyPasswordProvider)m.getContextualProperty(RSSEC_KEY_PSWD_PROVIDER); + Bus bus = (Bus)m.getExchange().get(Endpoint.class).get(Bus.class.getName()); + PrivateKey pk = CryptoUtils.loadPrivateKey(propLoc, bus, cb); + return new PrivateKeyJwsSignatureProvider(pk); + } + + public void writeJws(JwsCompactProducer p, OutputStream os) throws IOException { + JwsSignatureProvider theSigProvider = getInitializedSigProvider(); + p.signWith(theSigProvider); + IOUtils.copy(new ByteArrayInputStream(p.getSignedEncodedJws().getBytes("UTF-8")), os); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweClientResponseFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweClientResponseFilter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweClientResponseFilter.java index 0cf38fe..1cc35f6 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweClientResponseFilter.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweClientResponseFilter.java @@ -21,11 +21,13 @@ package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; +import javax.annotation.Priority; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; -public class JweClientResponseFilter extends AbstractJweDecryptingFilter implements ClientResponseFilter { +@Priority(Priorities.JWE_CLIENT_READ_PRIORITY) +public class JweClientResponseFilter extends AbstractJweDecryptingFilter implements ClientResponseFilter { @Override public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException { res.setEntityStream(new ByteArrayInputStream( http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweContainerRequestFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweContainerRequestFilter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweContainerRequestFilter.java index 9eb2ace..10a8ef2 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweContainerRequestFilter.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweContainerRequestFilter.java @@ -21,11 +21,13 @@ package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; import java.io.ByteArrayInputStream; import java.io.IOException; +import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; @PreMatching +@Priority(Priorities.JWE_SERVER_READ_PRIORITY) public class JweContainerRequestFilter extends AbstractJweDecryptingFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext context) throws IOException { http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java index e4698cb..fc6719b 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import java.security.PublicKey; +import javax.annotation.Priority; import javax.ws.rs.WebApplicationException; import javax.ws.rs.ext.WriterInterceptor; import javax.ws.rs.ext.WriterInterceptorContext; @@ -39,6 +40,7 @@ import org.apache.cxf.rs.security.oauth2.jwe.WrappedKeyJweEncryptor; import org.apache.cxf.rs.security.oauth2.jwt.Algorithm; import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +@Priority(Priorities.JWE_WRITE_PRIORITY) public class JweWriterInterceptor implements WriterInterceptor { private static final String RSSEC_ENCRYPTION_PROPS = "rs-security.encryption.properties"; private JweEncryptor encryptor; @@ -51,13 +53,9 @@ public class JweWriterInterceptor implements WriterInterceptor { ctx.proceed(); JweEncryptor theEncryptor = getInitializedEncryptor(); - if (theEncryptor == null) { - throw new SecurityException(); - } String jweContent = theEncryptor.encrypt(cos.getBytes()); IOUtils.copy(new ByteArrayInputStream(jweContent.getBytes("UTF-8")), actualOs); actualOs.flush(); - // TODO: figure out what to do with the content type } protected JweEncryptor getInitializedEncryptor() { @@ -66,11 +64,11 @@ public class JweWriterInterceptor implements WriterInterceptor { } Message m = JAXRSUtils.getCurrentMessage(); if (m == null) { - return null; + throw new SecurityException(); } String propLoc = (String)m.getContextualProperty(RSSEC_ENCRYPTION_PROPS); if (propLoc == null) { - return null; + throw new SecurityException(); } Bus bus = (Bus)m.getExchange().get(Endpoint.class).get(Bus.class.getName()); PublicKey pk = CryptoUtils.loadPublicKey(propLoc, bus); http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsClientResponseFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsClientResponseFilter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsClientResponseFilter.java new file mode 100644 index 0000000..0646722 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsClientResponseFilter.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.oauth2.jwt.jaxrs; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import javax.annotation.Priority; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; + +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.rs.security.oauth2.jws.JwsCompactConsumer; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.oauth2.jwt.JwtUtils; + +@Priority(Priorities.JWS_CLIENT_READ_PRIORITY) +public class JwsClientResponseFilter extends AbstractJwsReaderProvider implements ClientResponseFilter { + @Override + public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException { + JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); + JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(res.getEntityStream()), + getSigProperties()); + p.verifySignatureWith(theSigVerifier); + byte[] bytes = p.getDecodedJwsPayloadBytes(); + res.setEntityStream(new ByteArrayInputStream(bytes)); + String ct = JwtUtils.checkContentType(p.getJwtHeaders().getContentType()); + if (ct != null) { + res.getHeaders().putSingle("Content-Type", ct); + res.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsContainerRequestFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsContainerRequestFilter.java new file mode 100644 index 0000000..093fc3c --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsContainerRequestFilter.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; + +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.rs.security.oauth2.jws.JwsCompactConsumer; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.oauth2.jwt.JwtUtils; + +@PreMatching +@Priority(Priorities.JWS_SERVER_READ_PRIORITY) +public class JwsContainerRequestFilter extends AbstractJwsReaderProvider implements ContainerRequestFilter { + @Override + public void filter(ContainerRequestContext context) throws IOException { + + JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); + JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(context.getEntityStream()), + getSigProperties()); + p.verifySignatureWith(theSigVerifier); + byte[] bytes = p.getDecodedJwsPayloadBytes(); + context.setEntityStream(new ByteArrayInputStream(bytes)); + + String ct = JwtUtils.checkContentType(p.getJwtHeaders().getContentType()); + if (ct != null) { + context.getHeaders().putSingle("Content-Type", ct); + context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length)); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyReader.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyReader.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyReader.java new file mode 100644 index 0000000..2d3a144 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyReader.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.oauth2.jwt.jaxrs; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; + +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.rs.security.oauth2.jws.JwsJwtCompactConsumer; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureVerifier; +import org.apache.cxf.rs.security.oauth2.jwt.JwtToken; + +public class JwsJwtMessageBodyReader extends AbstractJwsReaderProvider + implements MessageBodyReader<JwtToken> { + + @Override + public boolean isReadable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) { + return cls == JwtToken.class; + } + + @Override + public JwtToken readFrom(Class<JwtToken> cls, Type t, Annotation[] anns, MediaType mt, + MultivaluedMap<String, String> headers, InputStream is) throws IOException, + WebApplicationException { + JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); + JwsJwtCompactConsumer p = new JwsJwtCompactConsumer(IOUtils.readStringFromStream(is), + getSigProperties()); + p.verifySignatureWith(theSigVerifier); + return p.getJwtToken(); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyWriter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyWriter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyWriter.java new file mode 100644 index 0000000..a94956e --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsJwtMessageBodyWriter.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyWriter; + +import org.apache.cxf.rs.security.oauth2.jws.JwsJwtCompactProducer; +import org.apache.cxf.rs.security.oauth2.jwt.JwtToken; + +public class JwsJwtMessageBodyWriter extends AbstractJwsWriterProvider + implements MessageBodyWriter<JwtToken> { + + @Override + public long getSize(JwtToken token, Class<?> cls, Type type, Annotation[] anns, MediaType mt) { + return -1; + } + + @Override + public boolean isWriteable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) { + return cls == JwtToken.class; + } + + @Override + public void writeTo(JwtToken token, Class<?> cls, Type type, Annotation[] anns, MediaType mt, + MultivaluedMap<String, Object> headers, OutputStream os) throws IOException, + WebApplicationException { + JwsJwtCompactProducer p = new JwsJwtCompactProducer(token); + writeJws(p, os); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsMessageBodyProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsMessageBodyProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsMessageBodyProvider.java deleted file mode 100644 index 0528f45..0000000 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsMessageBodyProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.security.PrivateKey; -import java.security.PublicKey; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.MessageBodyReader; -import javax.ws.rs.ext.MessageBodyWriter; - -import org.apache.cxf.Bus; -import org.apache.cxf.endpoint.Endpoint; -import org.apache.cxf.helpers.IOUtils; -import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.message.Message; -import org.apache.cxf.rs.security.oauth2.jws.JwsJwtCompactConsumer; -import org.apache.cxf.rs.security.oauth2.jws.JwsJwtCompactProducer; -import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureProperties; -import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureProvider; -import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureVerifier; -import org.apache.cxf.rs.security.oauth2.jws.PrivateKeyJwsSignatureProvider; -import org.apache.cxf.rs.security.oauth2.jws.PublicKeyJwsSignatureVerifier; -import org.apache.cxf.rs.security.oauth2.jwt.JwtToken; -import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; -import org.apache.cxf.rs.security.oauth2.utils.crypto.PrivateKeyPasswordProvider; - -public class JwsMessageBodyProvider implements - MessageBodyWriter<JwtToken>, MessageBodyReader<JwtToken> { - private static final String RSSEC_SIGNATURE_PROPS = "rs-security.signature.properties"; - private static final String RSSEC_KEY_PSWD_PROVIDER = "org.apache.rs.security.crypto.private.provider"; - - private JwsSignatureProperties sigProperties; - private JwsSignatureProvider sigProvider; - private JwsSignatureVerifier sigVerifier; - - @Override - public boolean isReadable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) { - return cls == JwtToken.class; - } - - @Override - public JwtToken readFrom(Class<JwtToken> cls, Type t, Annotation[] anns, MediaType mt, - MultivaluedMap<String, String> headers, InputStream is) throws IOException, - WebApplicationException { - JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(); - if (theSigVerifier == null) { - throw new SecurityException(); - } - JwsJwtCompactConsumer p = new JwsJwtCompactConsumer(IOUtils.readStringFromStream(is), - sigProperties); - p.verifySignatureWith(theSigVerifier); - return p.getJwtToken(); - } - - @Override - public long getSize(JwtToken token, Class<?> cls, Type type, Annotation[] anns, MediaType mt) { - return -1; - } - - @Override - public boolean isWriteable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) { - return cls == JwtToken.class; - } - - @Override - public void writeTo(JwtToken token, Class<?> cls, Type type, Annotation[] anns, MediaType mt, - MultivaluedMap<String, Object> headers, OutputStream os) throws IOException, - WebApplicationException { - - JwsSignatureProvider theSigProvider = getInitializedSigProvider(); - if (theSigProvider == null) { - throw new SecurityException(); - } - JwsJwtCompactProducer p = new JwsJwtCompactProducer(token); - p.signWith(theSigProvider); - IOUtils.copy(new ByteArrayInputStream(p.getSignedEncodedJws().getBytes("UTF-8")), os); - } - - - public void setSigProvider(JwsSignatureProvider sigProvider) { - this.sigProvider = sigProvider; - } - - - public void setSigVerifier(JwsSignatureVerifier sigVerifier) { - this.sigVerifier = sigVerifier; - } - - protected JwsSignatureProvider getInitializedSigProvider() { - if (sigProvider != null) { - return sigProvider; - } - Message m = JAXRSUtils.getCurrentMessage(); - if (m == null) { - return null; - } - String propLoc = (String)m.getContextualProperty(RSSEC_SIGNATURE_PROPS); - if (propLoc == null) { - return null; - } - - PrivateKeyPasswordProvider cb = (PrivateKeyPasswordProvider)m.getContextualProperty(RSSEC_KEY_PSWD_PROVIDER); - Bus bus = (Bus)m.getExchange().get(Endpoint.class).get(Bus.class.getName()); - PrivateKey pk = CryptoUtils.loadPrivateKey(propLoc, bus, cb); - return new PrivateKeyJwsSignatureProvider(pk); - } - - protected JwsSignatureVerifier getInitializedSigVerifier() { - if (sigVerifier != null) { - return sigVerifier; - } - Message m = JAXRSUtils.getCurrentMessage(); - if (m == null) { - return null; - } - String propLoc = (String)m.getContextualProperty(RSSEC_SIGNATURE_PROPS); - if (propLoc == null) { - return null; - } - - Bus bus = (Bus)m.getExchange().get(Endpoint.class).get(Bus.class.getName()); - PublicKey pk = CryptoUtils.loadPublicKey(propLoc, bus); - return new PublicKeyJwsSignatureVerifier(pk); - } - - public void setSigProperties(JwsSignatureProperties sigProperties) { - this.sigProperties = sigProperties; - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java new file mode 100644 index 0000000..a7beafb --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +import org.apache.cxf.io.CachedOutputStream; +import org.apache.cxf.rs.security.oauth2.jws.JwsCompactProducer; +import org.apache.cxf.rs.security.oauth2.jwt.Algorithm; +import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders; + +@Priority(Priorities.JWS_WRITE_PRIORITY) +public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements WriterInterceptor { + @Override + public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { + OutputStream actualOs = ctx.getOutputStream(); + CachedOutputStream cos = new CachedOutputStream(); + ctx.setOutputStream(cos); + ctx.proceed(); + + JwsCompactProducer p = new JwsCompactProducer(new JwtHeaders(Algorithm.SHA256withRSA.getJwtName()), + new String(cos.getBytes(), "UTF-8")); + writeJws(p, actualOs); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/Priorities.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/Priorities.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/Priorities.java new file mode 100644 index 0000000..49096b8 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/Priorities.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.oauth2.jwt.jaxrs; + +public final class Priorities { + public static final int JWE_SERVER_READ_PRIORITY = 1000; + public static final int JWE_WRITE_PRIORITY = 1001; + public static final int JWE_CLIENT_READ_PRIORITY = 1001; + public static final int JWS_SERVER_READ_PRIORITY = 1001; + public static final int JWS_WRITE_PRIORITY = 1000; + public static final int JWS_CLIENT_READ_PRIORITY = 1000; + private Priorities() { + + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/607f9359/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java index 924cd1a..5f934fe 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java @@ -128,6 +128,9 @@ public final class CryptoUtils { } } + public static Certificate loadCertificate(InputStream storeLocation, char[] storePassword, String alias) { + return loadCertificate(storeLocation, storePassword, alias, null); + } public static Certificate loadCertificate(InputStream storeLocation, char[] storePassword, String alias, String storeType) { try {
