I uploaded a sample project to github to see how HTTP Signature can be used with CXF:
- cxf-jaxrs-httpsig: This project contains a test that shows how to use the HTTP Signature functionality in Apache CXF to sign a message to/from a JAX-RS service.
1) Client configuration
The client configuration to both sign the outbound request and verify the service response is configured in the test code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
List<Object> providers = new ArrayList<>(); | |
providers.add(new CreateSignatureInterceptor()); | |
providers.add(new VerifySignatureClientFilter()); | |
String address = "http://localhost:" + PORT + "/doubleit/services"; | |
WebClient client = WebClient.create(address, providers, busFile.toString()); | |
client = client.type("application/xml"); | |
Map<String, Object> properties = new HashMap<String, Object>(); | |
properties.put("rs.security.signature.out.properties", "client.httpsig.properties"); | |
properties.put("rs.security.signature.in.properties", "service.httpsig.properties"); | |
WebClient.getConfig(client).getRequestContext().putAll(properties); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rs.security.keystore.type=jks | |
rs.security.keystore.password=cspass | |
rs.security.keystore.alias=myclientkey | |
rs.security.keystore.file=clientstore.jks | |
rs.security.key.password=ckpass | |
rs.security.http.signature.key.id=client-key-id |
By default CXF will add all HTTP headers to the signature. In addition, a client will also include the HTTP method and path using the "(request-target)" header. Also if the payload is not empty, it will be digested with the digest added to a "Digest" HTTP header, which is also signed. This provides payload integrity. By default, the signature algorithm is "rsa-sha256", of course it is possible to configure this. A secured request using HTTP signature looks like the following:
2) Service configuration
The service configuration is defined in spring. Two different JAX-RS providers are used on the service side - VerifySignatureFilter is used to verify a signature on the client request, and CreateSignatureInterceptor is used to sign the response message as per the client request.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<jaxrs:server address="http://localhost:${testutil.ports.Server}/doubleit"> | |
<jaxrs:serviceBeans> | |
<ref bean="serviceBean"/> | |
</jaxrs:serviceBeans> | |
<jaxrs:providers> | |
<bean class="org.apache.cxf.rs.security.httpsignature.filters.VerifySignatureFilter" /> | |
<bean class="org.apache.cxf.rs.security.httpsignature.filters.CreateSignatureInterceptor" /> | |
</jaxrs:providers> | |
<jaxrs:properties> | |
<entry key="rs.security.signature.in.properties" | |
value="client.httpsig.properties" /> | |
<entry key="rs.security.signature.out.properties" | |
value="service.httpsig.properties" /> | |
</jaxrs:properties> | |
</jaxrs:server> |