From 1b2c0dea036040ee41ca879fc25e2570e3e04ade Mon Sep 17 00:00:00 2001 From: Markus Haugsdal Date: Tue, 13 Jun 2023 23:15:12 +0200 Subject: [PATCH 1/5] [CXF-8811] add property usereqsigcert for server to use JWS certificate (x5c header) to sign the response JWE. --- .../jose/jaxrs/JwsContainerRequestFilter.java | 6 ++ .../security/jose/common/JoseConstants.java | 5 ++ .../cxf/rs/security/jose/jwe/JweUtils.java | 25 ++++++++ .../security/jose/jwejws/JAXRSJweJwsTest.java | 59 +++++++++++++++++++ .../jaxrs/security/alice.rs.properties | 1 + .../jaxrs/security/bob.rs.enc.out.properties | 26 ++++++++ .../systest/jaxrs/security/bob.rs.properties | 1 + .../jaxrs/security/jose/jwejws/server.xml | 20 +++++++ 8 files changed, 143 insertions(+) create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.enc.out.properties diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java index 337e874350b..720679edc25 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java @@ -31,10 +31,13 @@ import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.HttpUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; +import org.apache.cxf.phase.PhaseInterceptorChain; +import org.apache.cxf.rs.security.jose.common.JoseConstants; import org.apache.cxf.rs.security.jose.common.JoseUtils; import org.apache.cxf.rs.security.jose.jws.JwsCompactConsumer; import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; import org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier; +import org.apache.cxf.rt.security.crypto.CryptoUtils; import org.apache.cxf.security.SecurityContext; @PreMatching @@ -56,6 +59,9 @@ public void filter(ContainerRequestContext context) throws IOException { context.abortWith(JAXRSUtils.toResponse(400)); return; } + if(p.getJwsHeaders().containsHeader(JoseConstants.HEADER_X509_CHAIN)) { + JAXRSUtils.getCurrentMessage().getExchange().put("reqsigcert", CryptoUtils.decodeCertificate(p.getJwsHeaders().getX509Chain().get(0))); + } JoseUtils.validateRequestContextProperty(p.getJwsHeaders()); byte[] bytes = p.getDecodedJwsPayloadBytes(); diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java index 48d5cbc8b01..58f93210ec8 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java @@ -201,6 +201,11 @@ public final class JoseConstants extends RSSecurityConstants { */ public static final String ENABLE_UNSIGNED_JWT_PRINCIPAL = "rs.security.enable.unsigned-jwt.principal"; + /** + * Whether to use request signing certificate to create encryption provider + */ + public static final String USE_REQ_SIG_CERT = "useReqSigCert"; + /** * Whether to trace JOSE headers. */ diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java index cefad52f5a6..8784cc566d6 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -23,6 +23,7 @@ import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; @@ -62,6 +63,8 @@ import org.apache.cxf.rt.security.crypto.MessageDigestUtils; import org.apache.cxf.rt.security.rs.PrivateKeyPasswordProvider; +import static org.apache.cxf.rt.security.rs.RSSecurityConstants.RSSEC_KEY_STORE_ALIAS; + public final class JweUtils { private static final Logger LOG = LogUtils.getL7dLogger(JweUtils.class); @@ -453,6 +456,28 @@ public static KeyEncryptionProvider loadKeyEncryptionProvider(Properties props, headers.setKeyId(jwk.getKeyId()); } } + } else if (props.getProperty(RSSEC_KEY_STORE_ALIAS).equals(JoseConstants.USE_REQ_SIG_CERT)) { + var certificate = ((Certificate)PhaseInterceptorChain.getCurrentMessage().getExchange().get("reqsigcert")); + if (certificate == null) { + throw new JweException(JweException.Error.NO_ENCRYPTOR); + } + keyEncryptionProvider = getPublicKeyEncryptionProvider( + certificate.getPublicKey(), + keyAlgo + ); + + if (includeCert) { + headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props)); + } + if (includeCertSha1) { + KeyManagementUtils.setSha1DigestHeader(headers, m, props); + } else if (includeCertSha256) { + KeyManagementUtils.setSha256DigestHeader(headers, m, props); + } + if (includeKeyId && props.containsKey(RSSEC_KEY_STORE_ALIAS)) { + headers.setKeyId(props.getProperty(RSSEC_KEY_STORE_ALIAS)); + } + } else { keyEncryptionProvider = getPublicKeyEncryptionProvider( KeyManagementUtils.loadPublicKey(m, props), diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java index c08be2a9b0a..66a856c0e13 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java @@ -451,6 +451,65 @@ private BookStore createJweJwsBookStore(String address, return bean.create(BookStore.class); } + + @Test + public void testJweJwsUseReqSigCert(){ + String address = "https://localhost:" + PORT + "/jwejwsreqsigcert"; + 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<>(); + + // writer + JweWriterInterceptor jweWriter = new JweWriterInterceptor(); + jweWriter.setUseJweOutputStream(true); + JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); +// jwsWriter.setUseJwsOutputStream(true); + // reader + JweClientResponseFilter jweReader = new JweClientResponseFilter(); + JwsClientResponseFilter jwsReader = new JwsClientResponseFilter(); + + providers.add(jweWriter); + providers.add(jwsWriter); + + providers.add(jweReader); + providers.add(jwsReader); + bean.setProviders(providers); + + //CLIENT == ALICE + bean.getProperties(true).put( + "rs.security.encryption.out.properties", + "org/apache/cxf/systest/jaxrs/security/bob.rs.properties" + ); + bean.getProperties(true).put( + "rs.security.signature.out.properties", + "org/apache/cxf/systest/jaxrs/security/alice.rs.properties" + ); + bean.getProperties(true).put( + "rs.security.encryption.in.properties", + "org/apache/cxf/systest/jaxrs/security/alice.rs.properties" + ); + bean.getProperties(true).put( + "rs.security.signature.in.properties", + "org/apache/cxf/systest/jaxrs/security/bob.rs.properties" + ); + + bean.getProperties(true).put("jose.debug", true); + bean.getProperties(true).put("rs.security.signature.include.cert", "true"); +// bean.getProperties(true).put("rs.security.accept.public.key", "true"); + + + BookStore bs = bean.create(BookStore.class); + String text = bs.echoText("book"); + assertEquals("book", text); + + + } + @Test public void testJweAesGcmDirect() throws Exception { String address = "https://localhost:" + PORT + "/jweaesgcmdirect"; diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.properties index 800578257b8..5514465fd6e 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.properties +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.properties @@ -16,6 +16,7 @@ # under the License. rs.security.keystore.type=jks rs.security.keystore.password=password +rs.security.key.password=password rs.security.keystore.alias=alice rs.security.keystore.file=keys/alice.jks rs.security.encryption.content.algorithm=A128GCM diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.enc.out.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.enc.out.properties new file mode 100644 index 00000000000..0b345a78bdf --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.enc.out.properties @@ -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. +# +rs.security.keystore.type=jks +rs.security.keystore.password=password +rs.security.key.password=password +rs.security.keystore.alias=useReqSigCert +rs.security.keystore.file=keys/bob.jks +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.properties index dea95cd1ba4..617b63405a0 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.properties +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.properties @@ -18,6 +18,7 @@ # rs.security.keystore.type=jks rs.security.keystore.password=password +rs.security.key.password=password rs.security.keystore.alias=bob rs.security.keystore.file=keys/bob.jks rs.security.encryption.content.algorithm=A128GCM diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml index b948abe04aa..2cb68f31272 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml @@ -276,6 +276,26 @@ under the License. + + + + + + + + + + + + + + + + + + + + From bd34164024f43432895ea1de201b37bd010ec321 Mon Sep 17 00:00:00 2001 From: Markus Haugsdal Date: Thu, 24 Aug 2023 23:37:16 +0200 Subject: [PATCH 2/5] [CXF-8811] changed to public key from sigVerifier --- .../security/jose/jaxrs/JwsContainerRequestFilter.java | 10 +++------- .../org/apache/cxf/rs/security/jose/jwe/JweUtils.java | 6 +++--- .../jose/jws/PublicKeyJwsSignatureVerifier.java | 3 +++ .../jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java | 2 -- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java index 720679edc25..13a86c9bb3b 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java @@ -21,6 +21,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.Principal; +import java.security.PublicKey; import jakarta.annotation.Priority; import jakarta.ws.rs.HttpMethod; @@ -31,13 +32,10 @@ import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.HttpUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.phase.PhaseInterceptorChain; -import org.apache.cxf.rs.security.jose.common.JoseConstants; import org.apache.cxf.rs.security.jose.common.JoseUtils; import org.apache.cxf.rs.security.jose.jws.JwsCompactConsumer; import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier; import org.apache.cxf.rs.security.jose.jws.PublicKeyJwsSignatureVerifier; -import org.apache.cxf.rt.security.crypto.CryptoUtils; import org.apache.cxf.security.SecurityContext; @PreMatching @@ -59,9 +57,6 @@ public void filter(ContainerRequestContext context) throws IOException { context.abortWith(JAXRSUtils.toResponse(400)); return; } - if(p.getJwsHeaders().containsHeader(JoseConstants.HEADER_X509_CHAIN)) { - JAXRSUtils.getCurrentMessage().getExchange().put("reqsigcert", CryptoUtils.decodeCertificate(p.getJwsHeaders().getX509Chain().get(0))); - } JoseUtils.validateRequestContextProperty(p.getJwsHeaders()); byte[] bytes = p.getDecodedJwsPayloadBytes(); @@ -83,6 +78,7 @@ public void filter(ContainerRequestContext context) throws IOException { if (securityContext != null) { JAXRSUtils.getCurrentMessage().put(SecurityContext.class, securityContext); } + JAXRSUtils.getCurrentMessage().getExchange().put(PublicKey.class, ((PublicKeyJwsSignatureVerifier) theSigVerifier).getPublicKey()); } } @@ -104,7 +100,7 @@ public boolean isUserInRole(String arg0) { } return null; } - + protected boolean isMethodWithNoContent(String method) { return HttpMethod.DELETE.equals(method) || HttpUtils.isMethodWithNoRequestContent(method); } diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java index 8784cc566d6..4cc25c2bd6c 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -457,12 +457,12 @@ public static KeyEncryptionProvider loadKeyEncryptionProvider(Properties props, } } } else if (props.getProperty(RSSEC_KEY_STORE_ALIAS).equals(JoseConstants.USE_REQ_SIG_CERT)) { - var certificate = ((Certificate)PhaseInterceptorChain.getCurrentMessage().getExchange().get("reqsigcert")); - if (certificate == null) { + var publicKey = PhaseInterceptorChain.getCurrentMessage().getExchange().get(PublicKey.class); + if (publicKey == null) { throw new JweException(JweException.Error.NO_ENCRYPTOR); } keyEncryptionProvider = getPublicKeyEncryptionProvider( - certificate.getPublicKey(), + publicKey, keyAlgo ); diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java index bcc15edcd5b..7d3a338294b 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PublicKeyJwsSignatureVerifier.java @@ -101,6 +101,9 @@ public SignatureAlgorithm getAlgorithm() { public X509Certificate getX509Certificate() { return cert; } + public PublicKey getPublicKey() { + return key; + } @Override public JwsVerificationSignature createJwsVerificationSignature(JwsHeaders headers) { Signature sig = CryptoUtils.getVerificationSignature(key, diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java index 66a856c0e13..249938f1722 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java @@ -500,8 +500,6 @@ public void testJweJwsUseReqSigCert(){ bean.getProperties(true).put("jose.debug", true); bean.getProperties(true).put("rs.security.signature.include.cert", "true"); -// bean.getProperties(true).put("rs.security.accept.public.key", "true"); - BookStore bs = bean.create(BookStore.class); String text = bs.echoText("book"); From aa98f1d930846389e45bdbc44b1f0446b9f89370 Mon Sep 17 00:00:00 2001 From: Markus Haugsdal Date: Fri, 25 Aug 2023 13:34:49 +0200 Subject: [PATCH 3/5] [CXF-8811] fixed exception and added JWK test --- .../cxf/rs/security/jose/jwe/JweUtils.java | 50 ++++++++-------- .../security/jose/jwejws/JAXRSJweJwsTest.java | 59 +++++++++++++++++-- .../security/alice.jwk.enc.in.properties | 22 +++++++ .../security/alice.jwk.enc.out.properties | 22 +++++++ .../security/alice.jwk.sign.in.properties | 22 +++++++ .../security/alice.jwk.sign.out.properties | 22 +++++++ .../jaxrs/security/bob.jwk.enc.in.properties | 24 ++++++++ .../jaxrs/security/bob.jwk.enc.out.properties | 24 ++++++++ .../jaxrs/security/bob.jwk.sign.in.properties | 24 ++++++++ .../security/bob.jwk.sign.out.properties | 24 ++++++++ .../jaxrs/security/jose/jwejws/server.xml | 20 +++++++ 11 files changed, 285 insertions(+), 28 deletions(-) create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.in.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.out.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.in.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.out.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.in.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.out.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.in.properties create mode 100644 systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.out.properties diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java index 4cc25c2bd6c..141efcf34e5 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -430,7 +430,30 @@ public static KeyEncryptionProvider loadKeyEncryptionProvider(Properties props, boolean includeKeyId = JoseUtils.checkBooleanProperty(headers, props, m, JoseConstants.RSSEC_ENCRYPTION_INCLUDE_KEY_ID); - if (JoseConstants.HEADER_JSON_WEB_KEY.equals(props.get(JoseConstants.RSSEC_KEY_STORE_TYPE))) { + if (props.getProperty(RSSEC_KEY_STORE_ALIAS) != null && props.getProperty(RSSEC_KEY_STORE_ALIAS).equals(JoseConstants.USE_REQ_SIG_CERT)) { + var publicKey = PhaseInterceptorChain.getCurrentMessage().getExchange().get(PublicKey.class); + if (publicKey == null) { + throw new JweException(JweException.Error.NO_ENCRYPTOR); + } + keyEncryptionProvider = getPublicKeyEncryptionProvider( + publicKey, + keyAlgo + ); + + if (includeCert) { + headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props)); + } + if (includeCertSha1) { + KeyManagementUtils.setSha1DigestHeader(headers, m, props); + } else if (includeCertSha256) { + KeyManagementUtils.setSha256DigestHeader(headers, m, props); + } + if (includeKeyId && props.containsKey(RSSEC_KEY_STORE_ALIAS)) { + headers.setKeyId(props.getProperty(RSSEC_KEY_STORE_ALIAS)); + } + + } + else if (JoseConstants.HEADER_JSON_WEB_KEY.equals(props.get(JoseConstants.RSSEC_KEY_STORE_TYPE))) { JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.ENCRYPT); if (jwk != null) { keyAlgo = getKeyEncryptionAlgorithm(m, props, @@ -456,29 +479,8 @@ public static KeyEncryptionProvider loadKeyEncryptionProvider(Properties props, headers.setKeyId(jwk.getKeyId()); } } - } else if (props.getProperty(RSSEC_KEY_STORE_ALIAS).equals(JoseConstants.USE_REQ_SIG_CERT)) { - var publicKey = PhaseInterceptorChain.getCurrentMessage().getExchange().get(PublicKey.class); - if (publicKey == null) { - throw new JweException(JweException.Error.NO_ENCRYPTOR); - } - keyEncryptionProvider = getPublicKeyEncryptionProvider( - publicKey, - keyAlgo - ); - - if (includeCert) { - headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props)); - } - if (includeCertSha1) { - KeyManagementUtils.setSha1DigestHeader(headers, m, props); - } else if (includeCertSha256) { - KeyManagementUtils.setSha256DigestHeader(headers, m, props); - } - if (includeKeyId && props.containsKey(RSSEC_KEY_STORE_ALIAS)) { - headers.setKeyId(props.getProperty(RSSEC_KEY_STORE_ALIAS)); - } - - } else { + } + else { keyEncryptionProvider = getPublicKeyEncryptionProvider( KeyManagementUtils.loadPublicKey(m, props), props, diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java index c208a3273cf..ec6a5ec6eca 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jose/jwejws/JAXRSJweJwsTest.java @@ -451,9 +451,62 @@ private BookStore createJweJwsBookStore(String address, return bean.create(BookStore.class); } + @Test + public void testJweJwsJwkRsaUseReqSigCert(){ + String address = "https://localhost:" + PORT + "/jwejwsjwkreqsigcert"; + 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<>(); + + // writer + JweWriterInterceptor jweWriter = new JweWriterInterceptor(); + jweWriter.setUseJweOutputStream(true); + JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); + jwsWriter.setUseJwsOutputStream(true); + // reader + JweClientResponseFilter jweReader = new JweClientResponseFilter(); + JwsClientResponseFilter jwsReader = new JwsClientResponseFilter(); + + providers.add(jweWriter); + providers.add(jwsWriter); + + providers.add(jweReader); + providers.add(jwsReader); + bean.setProviders(providers); + + //CLIENT == ALICE + bean.getProperties(true).put( + "rs.security.encryption.out.properties", + "org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.out.properties" + ); + bean.getProperties(true).put( + "rs.security.signature.out.properties", + "org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.out.properties" + ); + bean.getProperties(true).put( + "rs.security.encryption.in.properties", + "org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.in.properties" + ); + bean.getProperties(true).put( + "rs.security.signature.in.properties", + "org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.in.properties" + ); + + bean.getProperties(true).put("jose.debug", true); + bean.getProperties(true).put("rs.security.signature.include.public.key", "true"); + + BookStore bs = bean.create(BookStore.class); + String text = bs.echoText("book"); + assertEquals("book", text); + } @Test - public void testJweJwsUseReqSigCert(){ + public void testJweJwsRsaUseReqSigCert(){ String address = "https://localhost:" + PORT + "/jwejwsreqsigcert"; JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); SpringBusFactory bf = new SpringBusFactory(); @@ -468,7 +521,7 @@ public void testJweJwsUseReqSigCert(){ JweWriterInterceptor jweWriter = new JweWriterInterceptor(); jweWriter.setUseJweOutputStream(true); JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); -// jwsWriter.setUseJwsOutputStream(true); + jwsWriter.setUseJwsOutputStream(true); // reader JweClientResponseFilter jweReader = new JweClientResponseFilter(); JwsClientResponseFilter jwsReader = new JwsClientResponseFilter(); @@ -504,8 +557,6 @@ public void testJweJwsUseReqSigCert(){ BookStore bs = bean.create(BookStore.class); String text = bs.echoText("book"); assertEquals("book", text); - - } @Test diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.in.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.in.properties new file mode 100644 index 00000000000..d8a002f8131 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.in.properties @@ -0,0 +1,22 @@ +# 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=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.out.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.out.properties new file mode 100644 index 00000000000..ed395549c20 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.enc.out.properties @@ -0,0 +1,22 @@ +# 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=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.in.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.in.properties new file mode 100644 index 00000000000..ed395549c20 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.in.properties @@ -0,0 +1,22 @@ +# 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=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.out.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.out.properties new file mode 100644 index 00000000000..d8a002f8131 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.jwk.sign.out.properties @@ -0,0 +1,22 @@ +# 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=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.in.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.in.properties new file mode 100644 index 00000000000..6563d4c3b9e --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.in.properties @@ -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. +# +rs.security.keystore.type=jwk +rs.security.keystore.alias=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.out.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.out.properties new file mode 100644 index 00000000000..a20d784a755 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.enc.out.properties @@ -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. +# +rs.security.keystore.type=jwk +rs.security.keystore.alias=useReqSigCert +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.in.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.in.properties new file mode 100644 index 00000000000..808772a52d7 --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.in.properties @@ -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. +# +rs.security.keystore.type=jwk +rs.security.keystore.alias=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.out.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.out.properties new file mode 100644 index 00000000000..6563d4c3b9e --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.jwk.sign.out.properties @@ -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. +# +rs.security.keystore.type=jwk +rs.security.keystore.alias=2011-04-29 +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPrivateSet.txt +rs.security.encryption.content.algorithm=A128GCM +rs.security.encryption.key.algorithm=RSA-OAEP +rs.security.signature.algorithm=RS256 diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml index 2cb68f31272..630f2508beb 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml @@ -296,6 +296,26 @@ under the License. + + + + + + + + + + + + + + + + + + + + From 3c8ff2522dfb165e0311b2119c035f86ce2e2a24 Mon Sep 17 00:00:00 2001 From: Markus Haugsdal Date: Mon, 28 Aug 2023 22:07:19 +0200 Subject: [PATCH 4/5] [CXF-8811] put public key saving in configureSecurityContext --- .../jose/jaxrs/JwsContainerRequestFilter.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java index 13a86c9bb3b..6a53449a672 100644 --- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java +++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java @@ -78,25 +78,27 @@ public void filter(ContainerRequestContext context) throws IOException { if (securityContext != null) { JAXRSUtils.getCurrentMessage().put(SecurityContext.class, securityContext); } - JAXRSUtils.getCurrentMessage().getExchange().put(PublicKey.class, ((PublicKeyJwsSignatureVerifier) theSigVerifier).getPublicKey()); + } } protected SecurityContext configureSecurityContext(JwsSignatureVerifier sigVerifier) { - if (sigVerifier instanceof PublicKeyJwsSignatureVerifier - && ((PublicKeyJwsSignatureVerifier)sigVerifier).getX509Certificate() != null) { - final Principal principal = - ((PublicKeyJwsSignatureVerifier)sigVerifier).getX509Certificate().getSubjectX500Principal(); - return new SecurityContext() { + if (sigVerifier instanceof PublicKeyJwsSignatureVerifier) { + JAXRSUtils.getCurrentMessage().getExchange().put(PublicKey.class, ((PublicKeyJwsSignatureVerifier) sigVerifier).getPublicKey()); + if (((PublicKeyJwsSignatureVerifier) sigVerifier).getX509Certificate() != null) { + final Principal principal = + ((PublicKeyJwsSignatureVerifier)sigVerifier).getX509Certificate().getSubjectX500Principal(); + return new SecurityContext() { - public Principal getUserPrincipal() { - return principal; - } + public Principal getUserPrincipal() { + return principal; + } - public boolean isUserInRole(String arg0) { - return false; - } - }; + public boolean isUserInRole(String arg0) { + return false; + } + }; + } } return null; } From 9f1e6785823fa74129772020433d27616e2a3284 Mon Sep 17 00:00:00 2001 From: Markus Haugsdal Date: Wed, 3 Jul 2024 20:26:28 +0200 Subject: [PATCH 5/5] removed commented lines --- .../apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml index 630f2508beb..0cf4a18a229 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/jose/jwejws/server.xml @@ -312,8 +312,6 @@ under the License. - -