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 00D791186B for ; Wed, 10 Sep 2014 16:59:13 +0000 (UTC) Received: (qmail 22359 invoked by uid 500); 10 Sep 2014 16:59:12 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 22302 invoked by uid 500); 10 Sep 2014 16:59:12 -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 22293 invoked by uid 99); 10 Sep 2014 16:59:12 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 10 Sep 2014 16:59:12 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7CF111ECAA; Wed, 10 Sep 2014 16:59:12 +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 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: git commit: [CXF-5954] Adding a JWS JWK HMac test Date: Wed, 10 Sep 2014 16:59:12 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/master b7a7916a3 -> b22f204d1 [CXF-5954] Adding a JWS JWK HMac test Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/b22f204d Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/b22f204d Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/b22f204d Branch: refs/heads/master Commit: b22f204d1ed95ff5dca49b9691ef3986b41c1c4c Parents: b7a7916 Author: Sergey Beryozkin Authored: Wed Sep 10 17:58:52 2014 +0100 Committer: Sergey Beryozkin Committed: Wed Sep 10 17:58:52 2014 +0100 ---------------------------------------------------------------------- .../cxf/rs/security/oauth2/jwk/JsonWebKey.java | 1 + .../cxf/rs/security/oauth2/jwt/Algorithm.java | 16 ++++++++- .../rs/security/oauth2/jwt/JwtConstants.java | 1 + .../jwt/jaxrs/AbstractJweDecryptingFilter.java | 12 ++++--- .../jwt/jaxrs/AbstractJwsReaderProvider.java | 20 ++++++++--- .../jwt/jaxrs/AbstractJwsWriterProvider.java | 33 ++++++++++++------ .../oauth2/jwt/jaxrs/JweWriterInterceptor.java | 14 +++++--- .../jwt/jaxrs/JwsJwtMessageBodyWriter.java | 8 ++++- .../oauth2/jwt/jaxrs/JwsWriterInterceptor.java | 36 +++++++++----------- .../jaxrs/security/jwt/JAXRSJweJwsTest.java | 23 +++++++++++++ .../cxf/systest/jaxrs/security/jwt/server.xml | 22 +++++++++--- .../jaxrs/security/certs/jwkPrivateSet.txt | 7 +++- .../jaxrs/security/secret.jws.properties | 19 +++++++++++ 13 files changed, 163 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java index 4131b46..fc82c5c 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwk/JsonWebKey.java @@ -195,4 +195,5 @@ public class JsonWebKey extends AbstractJwtObject { Algorithm.toJavaName(getAlgorithm())); } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java index b3e7914..cef22e6 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java @@ -177,5 +177,19 @@ public enum Algorithm { } return javaName; } - + public static boolean isAesKeyWrap(String algo) { + return JwtConstants.A128KW_ALGO.equals(algo) + || JwtConstants.A192KW_ALGO.equals(algo) + || JwtConstants.A256KW_ALGO.equals(algo); + } + public static boolean isAesGcmKeyWrap(String algo) { + return JwtConstants.A128GCM_ALGO.equals(algo) + || JwtConstants.A192GCMKW_ALGO.equals(algo) + || JwtConstants.A256GCMKW_ALGO.equals(algo); + } + public static boolean isHmacSign(String algo) { + return JwtConstants.HMAC_SHA_256_ALGO.equals(algo) + || JwtConstants.HMAC_SHA_384_ALGO.equals(algo) + || JwtConstants.HMAC_SHA_512_ALGO.equals(algo); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java index b4e8fce..003d2ec 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java @@ -41,6 +41,7 @@ public final class JwtConstants { 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"; http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJweDecryptingFilter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJweDecryptingFilter.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJweDecryptingFilter.java index a7d5fd8..4c67927 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJweDecryptingFilter.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/AbstractJweDecryptingFilter.java @@ -31,6 +31,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; +import org.apache.cxf.rs.security.oauth2.jwe.AesGcmWrapKeyDecryptionAlgorithm; import org.apache.cxf.rs.security.oauth2.jwe.AesWrapKeyDecryptionAlgorithm; import org.apache.cxf.rs.security.oauth2.jwe.JweCryptoProperties; import org.apache.cxf.rs.security.oauth2.jwe.JweDecryptionOutput; @@ -85,19 +86,22 @@ public class AbstractJweDecryptingFilter { keyDecryptionProvider = new RSAOaepKeyDecryptionAlgorithm(jwk.toRSAPrivateKey()); } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { SecretKey key = jwk.toSecretKey(); - // TODO: Introduce an algo family check - if (Algorithm.A128KW.getJwtName().equals(jwk.getAlgorithm())) { + if (Algorithm.isAesKeyWrap(jwk.getAlgorithm())) { keyDecryptionProvider = new AesWrapKeyDecryptionAlgorithm(key); - } + } else if (Algorithm.isAesGcmKeyWrap(jwk.getAlgorithm())) { + keyDecryptionProvider = new AesGcmWrapKeyDecryptionAlgorithm(key); + } // etc } else { // TODO: support elliptic curve keys - throw new SecurityException(); } } else { keyDecryptionProvider = new RSAOaepKeyDecryptionAlgorithm( (RSAPrivateKey)CryptoUtils.loadPrivateKey(m, props, CryptoUtils.RSSEC_DECRYPT_KEY_PSWD_PROVIDER)); } + if (keyDecryptionProvider == null) { + throw new SecurityException(); + } return new WrappedKeyJweDecryption(keyDecryptionProvider, cryptoProperties, null); } catch (SecurityException ex) { throw ex; http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/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 index 2dd6f1d..95ae1cc 100644 --- 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 @@ -28,9 +28,11 @@ import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.rs.security.oauth2.jwk.JsonWebKey; import org.apache.cxf.rs.security.oauth2.jwk.JwkUtils; +import org.apache.cxf.rs.security.oauth2.jws.HmacJwsSignatureProvider; 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.jwt.Algorithm; import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; public class AbstractJwsReaderProvider { @@ -66,15 +68,25 @@ public class AbstractJwsReaderProvider { } Bus bus = m.getExchange().getBus(); try { - RSAPublicKey pk = null; Properties props = ResourceUtils.loadProperties(propLoc, bus); + JwsSignatureVerifier theVerifier = null; if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(CryptoUtils.RSSEC_KEY_STORE_TYPE))) { JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props); - pk = jwk.toRSAPublicKey(); + if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { + theVerifier = new PublicKeyJwsSignatureVerifier(jwk.toRSAPublicKey()); + } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType()) + && Algorithm.isHmacSign(jwk.getAlgorithm())) { + theVerifier = + new HmacJwsSignatureProvider((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE)); + } else { + // TODO: support elliptic curve keys + } + } else { - pk = (RSAPublicKey)CryptoUtils.loadPublicKey(m, props); + theVerifier = new PublicKeyJwsSignatureVerifier( + (RSAPublicKey)CryptoUtils.loadPublicKey(m, props)); } - return new PublicKeyJwsSignatureVerifier(pk); + return theVerifier; } catch (SecurityException ex) { throw ex; } catch (Exception ex) { http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/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 index 06af4ab..c6c330b 100644 --- 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 @@ -31,9 +31,12 @@ import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.rs.security.oauth2.jwk.JsonWebKey; import org.apache.cxf.rs.security.oauth2.jwk.JwkUtils; +import org.apache.cxf.rs.security.oauth2.jws.HmacJwsSignatureProvider; 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.jwt.Algorithm; +import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders; import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; public class AbstractJwsWriterProvider { @@ -47,7 +50,7 @@ public class AbstractJwsWriterProvider { this.sigProvider = signatureProvider; } - protected JwsSignatureProvider getInitializedSigProvider() { + protected JwsSignatureProvider getInitializedSigProvider(JwtHeaders headers) { if (sigProvider != null) { return sigProvider; } @@ -58,33 +61,43 @@ public class AbstractJwsWriterProvider { throw new SecurityException(); } try { - RSAPrivateKey pk = null; Properties props = ResourceUtils.loadProperties(propLoc, m.getExchange().getBus()); + JwsSignatureProvider theSigProvider = null; String rsaSignatureAlgo = null; if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(CryptoUtils.RSSEC_KEY_STORE_TYPE))) { //TODO: Private JWK sets can be JWE encrypted JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props); - pk = jwk.toRSAPrivateKey(); rsaSignatureAlgo = jwk.getAlgorithm(); + if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { + theSigProvider = new PrivateKeyJwsSignatureProvider(jwk.toRSAPrivateKey()); + } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType()) + && Algorithm.isHmacSign(rsaSignatureAlgo)) { + theSigProvider = + new HmacJwsSignatureProvider((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE)); + } else { + // TODO: support elliptic curve keys + } } else { - pk = (RSAPrivateKey)CryptoUtils.loadPrivateKey(m, props, + RSAPrivateKey pk = (RSAPrivateKey)CryptoUtils.loadPrivateKey(m, props, CryptoUtils.RSSEC_SIG_KEY_PSWD_PROVIDER); + theSigProvider = new PrivateKeyJwsSignatureProvider(pk); } if (rsaSignatureAlgo == null) { rsaSignatureAlgo = props.getProperty(JSON_WEB_SIGNATURE_ALGO_PROP); } - PrivateKeyJwsSignatureProvider provider = new PrivateKeyJwsSignatureProvider(pk); - provider.setDefaultJwtAlgorithm(rsaSignatureAlgo); - return provider; + headers.setAlgorithm(rsaSignatureAlgo); + if (theSigProvider == null) { + throw new SecurityException(); + } + return theSigProvider; } catch (SecurityException ex) { throw ex; } catch (Exception ex) { throw new SecurityException(ex); } } - - protected void writeJws(JwsCompactProducer p, OutputStream os) throws IOException { - JwsSignatureProvider theSigProvider = getInitializedSigProvider(); + protected void writeJws(JwsCompactProducer p, JwsSignatureProvider theSigProvider, OutputStream os) + throws IOException { p.signWith(theSigProvider); IOUtils.copy(new ByteArrayInputStream(p.getSignedEncodedJws().getBytes("UTF-8")), os); } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/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 ac3338b..2c1f6e0 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 @@ -39,6 +39,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; +import org.apache.cxf.rs.security.oauth2.jwe.AesGcmWrapKeyEncryptionAlgorithm; import org.apache.cxf.rs.security.oauth2.jwe.AesWrapKeyEncryptionAlgorithm; import org.apache.cxf.rs.security.oauth2.jwe.JweCompactProducer; import org.apache.cxf.rs.security.oauth2.jwe.JweEncryptionProvider; @@ -68,6 +69,9 @@ public class JweWriterInterceptor implements WriterInterceptor { private JwtHeadersWriter writer = new JwtTokenReaderWriter(); @Override public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { + + //ctx.setMediaType(JAXRSUtils.toMediaType(JwtConstants.MEDIA_TYPE_JOSE_JSON)); + OutputStream actualOs = ctx.getOutputStream(); JweEncryptionProvider theEncryptionProvider = getInitializedEncryptionProvider(); @@ -134,20 +138,22 @@ public class JweWriterInterceptor implements WriterInterceptor { keyEncryptionProvider = new RSAOaepKeyEncryptionAlgorithm(jwk.toRSAPublicKey()); } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { SecretKey key = jwk.toSecretKey(); - // TODO: Introduce an algo family check - if (Algorithm.A128KW.getJwtName().equals(keyEncryptionAlgo)) { + if (Algorithm.isAesKeyWrap(keyEncryptionAlgo)) { keyEncryptionProvider = new AesWrapKeyEncryptionAlgorithm(key, keyEncryptionAlgo); + } else if (Algorithm.isAesGcmKeyWrap(keyEncryptionAlgo)) { + keyEncryptionProvider = new AesGcmWrapKeyEncryptionAlgorithm(key, keyEncryptionAlgo); } - // etc } else { // TODO: support elliptic curve keys - throw new SecurityException(); } } else { keyEncryptionProvider = new RSAOaepKeyEncryptionAlgorithm( (RSAPublicKey)CryptoUtils.loadPublicKey(m, props)); } + if (keyEncryptionProvider == null) { + throw new SecurityException(); + } if (keyEncryptionAlgo == null) { keyEncryptionAlgo = props.getProperty(JSON_WEB_ENCRYPTION_KEY_ALGO_PROP); } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/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 index a94956e..595b83c 100644 --- 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 @@ -29,6 +29,9 @@ 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.jws.JwsSignatureProvider; +import org.apache.cxf.rs.security.oauth2.jwt.JwtConstants; +import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders; import org.apache.cxf.rs.security.oauth2.jwt.JwtToken; public class JwsJwtMessageBodyWriter extends AbstractJwsWriterProvider @@ -49,6 +52,9 @@ public class JwsJwtMessageBodyWriter extends AbstractJwsWriterProvider MultivaluedMap headers, OutputStream os) throws IOException, WebApplicationException { JwsJwtCompactProducer p = new JwsJwtCompactProducer(token); - writeJws(p, os); + JwtHeaders jwtHeaders = new JwtHeaders(); + JwsSignatureProvider sigProvider = getInitializedSigProvider(jwtHeaders); + jwtHeaders.setContentType(JwtConstants.TYPE_JWT); + writeJws(p, sigProvider, os); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/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 index 2a0afcd..1e7f706 100644 --- 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 @@ -32,6 +32,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.rs.security.oauth2.jws.JwsCompactProducer; import org.apache.cxf.rs.security.oauth2.jws.JwsOutputStream; import org.apache.cxf.rs.security.oauth2.jws.JwsSignature; +import org.apache.cxf.rs.security.oauth2.jws.JwsSignatureProvider; import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders; import org.apache.cxf.rs.security.oauth2.jwt.JwtHeadersWriter; import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenReaderWriter; @@ -45,20 +46,14 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W private JwtHeadersWriter writer = new JwtTokenReaderWriter(); @Override public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { + //ctx.setMediaType(JAXRSUtils.toMediaType(JwtConstants.MEDIA_TYPE_JOSE_JSON)); + JwtHeaders headers = new JwtHeaders(); + JwsSignatureProvider sigProvider = getInitializedSigProvider(headers); + setContentTypeIfNeeded(headers, ctx); + OutputStream actualOs = ctx.getOutputStream(); - String ctString = null; - if (contentTypeRequired) { - MediaType mt = ctx.getMediaType(); - if (mt != null) { - ctString = JAXRSUtils.mediaTypeToString(mt); - } - } if (useJwsOutputStream) { - JwtHeaders headers = new JwtHeaders(); - JwsSignature jwsSignature = getInitializedSigProvider().createJwsSignature(headers); - if (ctString != null) { - headers.setContentType(ctString); - } + JwsSignature jwsSignature = sigProvider.createJwsSignature(headers); JwsOutputStream jwsStream = new JwsOutputStream(actualOs, jwsSignature); byte[] headerBytes = writer.headersToJson(headers).getBytes("UTF-8"); Base64UrlUtility.encodeAndStream(headerBytes, 0, headerBytes.length, jwsStream); @@ -73,15 +68,11 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W CachedOutputStream cos = new CachedOutputStream(); ctx.setOutputStream(cos); ctx.proceed(); - - JwtHeaders headers = new JwtHeaders(); - if (ctString != null) { - headers.setContentType(ctString); - } JwsCompactProducer p = new JwsCompactProducer(headers, new String(cos.getBytes(), "UTF-8")); - writeJws(p, actualOs); + writeJws(p, sigProvider, actualOs); } } + public void setContentTypeRequired(boolean contentTypeRequired) { this.contentTypeRequired = contentTypeRequired; } @@ -92,5 +83,12 @@ public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements W public void setWriter(JwtHeadersWriter writer) { this.writer = writer; } - + private void setContentTypeIfNeeded(JwtHeaders headers, WriterInterceptorContext ctx) { + if (contentTypeRequired) { + MediaType mt = ctx.getMediaType(); + if (mt != null) { + headers.setContentType(JAXRSUtils.mediaTypeToString(mt)); + } + } + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java index 85bcf36..b7eb813 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java @@ -136,6 +136,29 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { doTestJweJwsRsa(address, hmacProvider); } + @Test + public void testJwsJwkHMac() throws Exception { + String address = "https://localhost:" + PORT + "/jwsjwkhmac"; + JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = JAXRSJweJwsTest.class.getResource("client.xml"); + Bus springBus = bf.createBus(busFile.toString()); + bean.setBus(springBus); + bean.setServiceClass(BookStore.class); + bean.setAddress(address); + List providers = new LinkedList(); + JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); + jwsWriter.setUseJwsOutputStream(true); + providers.add(jwsWriter); + providers.add(new JwsClientResponseFilter()); + bean.setProviders(providers); + bean.getProperties(true).put("rs.security.signature.properties", + "org/apache/cxf/systest/jaxrs/security/secret.jws.properties"); + BookStore bs = bean.create(BookStore.class); + String text = bs.echoText("book"); + assertEquals("book", text); + } + private void doTestJweJwsRsa(String address, JwsSignatureProvider jwsSigProvider) throws Exception { JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml index eaa9949..57cad2d 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml @@ -79,8 +79,8 @@ under the License. - - + + @@ -89,8 +89,8 @@ under the License. - - + + @@ -134,7 +134,7 @@ under the License. - + @@ -144,6 +144,18 @@ under the License. + + + + + + + + + + + + http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt index 491e57b..785f553 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt @@ -9,6 +9,11 @@ {"kty":"oct", "alg":"A128KW", "k":"GawgguFyGrWKav7AX4VKUg", - "kid":"AesWrapKey"} + "kid":"AesWrapKey"}, + + {"kty":"oct", + "alg":"HS256", + "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow", + "kid":"HMACKey"} ] } http://git-wip-us.apache.org/repos/asf/cxf/blob/b22f204d/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/secret.jws.properties ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/secret.jws.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/secret.jws.properties new file mode 100644 index 0000000..d050b71 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/secret.jws.properties @@ -0,0 +1,19 @@ +# 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. +rs.security.keystore.type=jwk +rs.security.keystore.alias=HMACKey +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt