Skip to content

CXF-8811: Use request JWS signing key to encrypt JWE response#1303

Open
mjhaugsdal wants to merge 20 commits intoapache:mainfrom
mjhaugsdal:feature/CXF-8811
Open

CXF-8811: Use request JWS signing key to encrypt JWE response#1303
mjhaugsdal wants to merge 20 commits intoapache:mainfrom
mjhaugsdal:feature/CXF-8811

Conversation

@mjhaugsdal
Copy link

@mjhaugsdal mjhaugsdal commented Jun 13, 2023

Summary

Adds support for using the client's JWS request signing public key to encrypt the server's JWE response. This is the JOSE equivalent of the existing useReqSigCert feature in CXF's WS-Security/XML Security module.

Use case

In JWS+JWE request-response flows, the server may not have the client's public key pre-configured. With this feature, the server can extract the public key from the verified JWS request signature and use it to encrypt the JWE response — ensuring only the original requester can decrypt it.

Configuration

Set rs.security.keystore.alias to useReqSigCert in the server's encryption output properties:

rs.security.keystore.alias=useReqSigCert
rs.security.encryption.content.algorithm=A128GCM
rs.security.encryption.key.algorithm=RSA-OAEP

The server must also have rs.security.accept.public.key=true to accept client-provided public keys for JWS verification.

Changes

  • JwsContainerRequestFilter: Stores the verified JWS signature's PublicKey on the Exchange so it's available during response encryption
  • JweUtils.loadKeyEncryptionProvider(): When alias is useReqSigCert, retrieves the stored public key from the exchange instead of loading from keystore
  • PublicKeyJwsSignatureVerifier: Adds getPublicKey() accessor
  • JoseConstants: Adds USE_REQ_SIG_CERT constant (matches existing WS-Security convention)
  • Tests: Two new test methods (testJweJwsRsaUseReqSigCert and testJweJwsJwkRsaUseReqSigCert) with JKS and JWK keystore variants

Security note

This feature requires rs.security.accept.public.key=true, which means the server trusts public keys provided in JWS headers. In production, this should be combined with additional trust mechanisms (e.g., mTLS at the transport layer, or certificate chain validation against a trusted CA).

🤖 Generated with Claude Code

@mjhaugsdal mjhaugsdal changed the title [CXF-8811] CXF-8811 Jun 23, 2023
@gnodet gnodet changed the title CXF-8811 CXF-8811: Use request JWS signing key to encrypt JWE response Mar 11, 2026
- Remove broken cert/sha header code from the useReqSigCert path in
  JweUtils: when alias is "useReqSigCert", the cert headers tried to
  look up a certificate with that alias in the keystore, which would
  fail at runtime since no such alias exists.
- Improve USE_REQ_SIG_CERT Javadoc to clarify it is a magic alias
  value, not a boolean flag.
- Add missing throws Exception on useReqSigCert test methods.
- Extract common helper createUseReqSigCertBookStore() to reduce
  duplicated test boilerplate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

Review findings and fixes

I've performed an in-depth review of this PR and pushed a fix commit (771d279) addressing the following issues:

Fixed issues

  1. Bug: cert/sha headers in useReqSigCert path would fail at runtime — In JweUtils, when the alias is useReqSigCert, the code for includeCert/includeCertSha1/includeCertSha256 called KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props) which reads the alias from props, getting "useReqSigCert", and tries to look it up in the keystore. Since no certificate with that alias exists, this would throw at runtime. Currently dead code in the tests (no include flags set in the properties files), but was a latent bug. Removed the broken cert header blocks from the useReqSigCert branch.

  2. USE_REQ_SIG_CERT Javadoc was misleading — The Javadoc read "Whether to use request signing certificate to create encryption provider" which sounds like a boolean flag. Updated it to clarify this is a magic value for rs.security.keystore.alias, mirroring the WS-Security convention.

  3. Missing throws Exception on testJweJwsJwkRsaUseReqSigCert() and testJweJwsRsaUseReqSigCert() test methods, unlike all other test methods in the class.

  4. Test boilerplate deduplication — Extracted common setup into createUseReqSigCertBookStore() helper, reducing ~90 lines of duplicated code to ~30.

Review notes (no action needed)

  1. Security model is sound — The useReqSigCert feature requires rs.security.accept.public.key=true as an explicit opt-in on the server, and the test endpoints run over mutual TLS. This correctly mirrors the WS-Security useReqSigCert pattern.

  2. PublicKey stored on Exchange unconditionally — In JwsContainerRequestFilter.configureSecurityContext(), the public key is stored on the Exchange whenever a PublicKeyJwsSignatureVerifier is used, even if the server doesn't use useReqSigCert. This is harmless since the Exchange is request-scoped, and it keeps the code simple.

@mjhaugsdal
Copy link
Author

mjhaugsdal commented Mar 11, 2026

@gnodet thank you for the feedback. This was a wanted feature on my team years ago but I never got confirmed if this is an actual wanted feature or not in CXF, so I have not looked at it for years now.

@gnodet gnodet marked this pull request as ready for review March 11, 2026 14:20
Add required ASF license header prefix (#\n#\n) to properties files
to satisfy the CXF RegexpHeader checkstyle rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants