Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

CXF adds support for the HTTP Signatures draft spec since CXF 3.3.0. This provides an alternative to providing message integrity other than XML Security and JOSE, and in fact provides a stronger measure of message integrity as it allows the incorporation of HTTP headers in the signature, including the HTTP method and path.

Maven Dependencies

Having the following dependency will let developers write JOSE JWS or JWE code:The following dependency is required to use CXF's HTTP Signature implementation.

Code Block
xml
xml
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-security-http-signature</artifactId>
  <version>3.3.1</version>
</dependency>

Configuration

CXF supports HTTP Signature creation and verification on both the client and service side.

Providers

To enable HTTP

...

Signature in CXF, it is necessary to add one of the following providers to the client or endpoint:

  • Client Outbound Signature Creation: org.apache.cxf.rs.security.httpsignature.filters.CreateSignatureClientFilter
  • Client Inbound Signature Verification: org.apache.cxf.rs.security.httpsignature.filters.VerifySignatureClientFilter
  • Service Outbound Signature Creation: org.apache.cxf.rs.security.httpsignature.filters.CreateSignatureFilter
  • Service Inbound Signature Verification: org.apache.cxf.rs.security.httpsignature.filters.VerifySignatureFilter

For example in code:

Code Block
languagejava
titleWebClient Config
CreateSignatureClientFilter signatureFilter = new CreateSignatureClientFilter();

String address = "http://localhost:" + PORT + "/httpsig/bookstore/books";
WebClient client =
    WebClient.create(address, Collections.singletonList(signatureFilter), busFile.toString());

and in Spring:

Code Block
titleSpring Config
<bean id="httpSignatureVerifier" class="org.apache.cxf.rs.security.httpsignature.filters.VerifySignatureFilter">
    <property name="messageVerifier" ref="messageVerifier"/>
</bean>
    
<jaxrs:server address="http://localhost:${testutil.ports.jaxrs-httpsignature}/httpsig">
   <jaxrs:serviceBeans>
       <ref bean="serviceBean"/>
   </jaxrs:serviceBeans>
   <jaxrs:providers>
       <ref bean="httpSignatureVerifier"/>
   </jaxrs:providers>
</jaxrs:server>

Fine grained Configuration

As well as adding the desired providers (see above), we need to configure them (for example the keys to use, the headers to sign, etc.). There are two options for doing this. In this section we'll look at configuring the providers directly, which allows for a more fine-grained configuration. See below for an alternative using configuration properties that retrieves keys from keystores.

For outbound signature we need to configure the CreateSignatureClientFilter + CreateSignatureFilter providers with a MessageSigner instance. The MessageSigner contains a number of different constructors that can be used depending on the desired functionality. At a minimum, we need to supply the PrivateKey instance to sign the message, as well as the "Key Id" as defined in the spec. We can also supply the signature algorithm name - if not specified this defaults to "rsa-sha256". Similarly we can supply the security provider name, which defaults to "SunRsaSign".

We can also supply a list of HTTP headers to sign. By default it signs all of the HTTP headers that are made available to it by CXF. On the client side it will also sign the HTTP method and Path via "(request-target)".

Here is an example from the tests:

Code Block
languagejava
CreateSignatureClientFilter signatureFilter = new CreateSignatureClientFilter();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(ClassLoaderUtils.getResourceAsStream("keys/alice.jks", this.getClass()),
    "password".toCharArray());
PrivateKey privateKey = (PrivateKey)keyStore.getKey("alice", "password".toCharArray());
assertNotNull(privateKey);

MessageSigner messageSigner = new MessageSigner(privateKey, "alice-key-id");
signatureFilter.setMessageSigner(messageSigner);

String address = "http://localhost:" + PORT + "/httpsig/bookstore/books";
WebClient client =
    WebClient.create(address, Collections.singletonList(signatureFilter), busFile.toString());
client.type("application/xml").accept("application/xml");

For signature verification, we need to supply the VerifySignatureClientFilter and VerifySignatureFilter instances with a MessageVerifier instance. At a minimum, we need to configure the MessageVerifier with a PublicKeyProvider instance, which is an interface which supplies the public key required to verify the signature. As per MessageSigner, we can also specify the signature algorithm that is required, as well as the Security Provider. It defaults to the same values as documented for MessageSigner above. We can also specify a list of HTTP headers which must be signed.

Here is an example from the tests:

Code Block
<bean id="publicKeyProvider" class="org.apache.cxf.systest.jaxrs.security.httpsignature.CustomPublicKeyProvider"/>
<bean id="messageVerifier" class="org.apache.cxf.rs.security.httpsignature.MessageVerifier">
    <constructor-arg>
        <ref bean="publicKeyProvider"/>
    </constructor-arg>
    <constructor-arg>
        <util:list>
            <value>(request-target)</value>
        </util:list>
    </constructor-arg>
</bean>
<bean id="httpSignatureVerifier" class="org.apache.cxf.rs.security.httpsignature.filters.VerifySignatureFilter">
    <property name="messageVerifier" ref="messageVerifier"/>
</bean>
    
<jaxrs:server address="http://localhost:${testutil.ports.jaxrs-httpsignature}/httpsig">
    <jaxrs:serviceBeans>
        <ref bean="serviceBean"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <ref bean="httpSignatureVerifier"/>
    </jaxrs:providers>
</jaxrs:server>


Configuration Properties

...

The following configuration properties can be used to configure HTTP Signature with the various filters. Note that they are shared for the most part with JAX-RS JOSE.

...