Apache CXF - cannot add binary signature token to SOAP message

26 views Asked by At

I want to add a binary signature token (BST) to my WSDL-generated SOAP messages, but when I explicitly set WSHandlerConstants.SIG_KEY_ID to "DirectReference" instead of omitting the line of code, my STAX interceptor doesn't generate an XML of the SOAP message anymore (gives a null). When I'm not using "DirectReference" and leave it as default, my generated XML SOAP message contains a <ds:X509IssuerSerial> tag. This is the code:

    SomeWsdlWebService service = new SomeWsdlWebService();
    SomeWebServicePort port = service.SomeWebServicePort();
    
    Client client = ClientProxy.getClient(port);
    Endpoint endpoint = client.getEndpoint();
    
    Map<String, Object> props = new HashMap<String, Object>();
    props.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP);
    props.put(WSHandlerConstants.USER, "EXAMPLE_ALIAS");
    props.put(WSHandlerConstants.PW_CALLBACK_CLASS, CallbackPasswordHandler.class.getName());
    props.put(WSHandlerConstants.SIG_PROP_FILE, "client.properties");
    props.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
    // Unsure if this is needed
    // props.put(WSHandlerConstants.SIGNATURE_PARTS, "{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken");
 
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
    endpoint.getOutInterceptors().add(wssOut);
    
    EchoBuyerClient echoClient = new EchoClient(port);
    MessageAckType messageAckType = echoBuyerClient.sendEchoBuyerMsg("test");

The client.properites file:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=EXAMPLE_PASSWORD
org.apache.ws.security.crypto.merlin.keystore.alias=EXAMPLE_ALIAS
org.apache.ws.security.crypto.merlin.file=./certs/EXAMPLE_JKS.jks

Obviously, names and values are placeholders. I've verified that each entry is being correctly loaded. The JKS contains multiple certificates and a private key. Using the same JKS in a separate test project, the following code works flawlessly:

WSSecSignature signature = new WSSecSignature();
WSSecHeader header = new WSSecHeader();
WSSecTimestamp timestamp = new WSSecTimestamp();

Document document = xmlToDoc(message);
header.setMustUnderstand(true);
signature.setSignatureAlgorithm(WSConstants.C14N_EXCL_OMIT_COMMENTS);
signature.setSignatureAlgorithm(WSConstants.RSA);
signature.setUserInfo("EXAMPLE_ALIAS", "EXAMPLE_PASSWORD");
signature.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);

try {
    header.insertSecurityHeader(document);
    timestamp.build(document, header);
    signature.build(document, crypto, header);
} catch (WSSecurityException e) {
    throw e;
}

Finally, don't know if this is relevant, but I'll list my Maven dependencies (had massive issues with dependency compatibility):

<dependencies>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-ws-security</artifactId>
        <version>3.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>3.2.4</version>
    </dependency>
</dependencies>

Considering I've built the aforementioned webservice through a WSDL file, I'd prefer to use apache cxf interceptors instead of manually modifying XML elements. However, I'm willing to do if it's the only way.

Using the debugger, I tried following the flow of the program and I've noticed usually there's a lot of null values involved. Honestly, I have no idea what I'm doing wrong here; a lot of other examples I've seen online are simpler than what I provided yet they work.

0

There are 0 answers