I am trying to generate a SOAP request using Apache CXF WS-Security similar to the following request(I generated it using SoapUI) :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<ds:Signature Id="SIG-xxx" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="soapenv"
xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#xxxx">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList=""
xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>xxxx</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>xxxx
</ds:SignatureValue>
<ds:KeyInfo Id="xxxxx">
<wsse:SecurityTokenReference wsu:Id="xxxxx">
<wsse:KeyIdentifier
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">
xxxx
</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="id-xxx"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<v3:AccountRequest
xmlns:v3="http://services.mysiste.com/V3">
<Request>
<SearchParametersBlock>
<MktCd>
<MktCdData>
<MktCd>US</MktCd>
</MktCdData>
</MktCd>
</SearchParametersBlock>
</Request>
</v3:AccountRequest>
</soapenv:Body>
</soapenv:Envelope>
I am using the following code to generate my Java client :
Properties signatureProperties = new Properties();
signatureProperties.put("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
signatureProperties.put("org.apache.ws.security.crypto.merlin.keystore.type",
"jks");
signatureProperties.put("org.apache.ws.security.crypto.merlin.keystore.file",
"server.jks");
signatureProperties.put("org.apache.ws.security.crypto.merlin.keystore.password",
"password");
signatureProperties.put("org.apache.ws.security.crypto.merlin.keystore.alias",
"myAlias");
signatureProperties.put("org.apache.ws.security.crypto.merlin.keystore.private.password", "password");
Map<String,Object> outProps = new HashMap<>();
outProps.put(WSHandlerConstants.USER, "myAlias");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "X509KeyIdentifier");
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServiceKeystorePasswordCallback.class.getName());
outProps.put(WSHandlerConstants.SIG_ALGO, "http://www.w3.org/2000/09/xmldsig#sha1");
outProps.put(WSHandlerConstants.SIG_C14N_ALGO, "http://www.w3.org/2001/10/xml-exc-c14n#");
outProps.put(WSHandlerConstants.SIG_PROP_REF_ID, "signatureProperties");
outProps.put("signatureProperties", signatureProperties);
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(this.service);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssIn);
But I am experiencing the following error : "Security processing failed (actions mismatch)"
I traced the exception and it boils down to the following snippet
if (!checkReceiverResultsAnyOrder(wsResult, actions)) {
LOG.warning("Security processing failed (actions mismatch)");
throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
}
Where actions != wsResult(it is empty)
I am not sure how to populate wsResult in this case. Any help would be greatly appreciated
Instead of WSS4JInInterceptor, I had to use a WSS4JOutInterceptor
WSS4JOutInterceptor outInterceptor = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(outInterceptor);