I am currently developing a WS client that needs to sign its requests before sending them to the server. I have a private key and a certificate for this purpose but I am struggling with the security header. The expected structure of the output XML should be something like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd"><wsse:BinarySecurityToken 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" wsu:Id="CertId-45..."
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-
1.0.xsd"> ... </wsse:BinarySecurityToken><ds:Signature Id="Signature-13"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-14">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>62...</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
...
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-...">
<wsse:SecurityTokenReference wsu:Id="STRId-..." xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-wssecurity-utility-1.0.xsd"><wsse:Reference URI="#CertId-..." ValueType="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature></wsse:Security></soapenv:Header>
<soapenv:Body wsu:Id="id-14" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
I tried using xmlseclibs but I can't figure out how to include all the required information since the examples are rather basic.
I suppose I could go the DIY way and manually build the headers but I would like to keep it as simple as possible.
Any clues?
Additional information
I am currently using SoapClient for this task. Thing is, I don't know how to do this exactly. The XML that I am sending requires signing its content and I have done so manually (using a c14n function and calculating its digest ..). However, in order to do the same for the whole body I'd need access to the raw XML (I suppose) so I do not think that would work.
I have not tried to create SOAP headers manually as I am trying to avoid any hacks. I am looking for something that is both easy to implement and easy to work on.
My code currently looks like this (keeping it to a minimum for improved readability):
$context = stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
'ciphers'=>'SSLv3'
)
));
$client = new SoapClient($url, array(
//'connection_timeout' => 100,
/* 'passphrase' => $pass,
'local_cert' => $keystore,*/
'stream_context' => $context,
// 'connection_timeout' => 1,
'trace' => true,
'exceptions' => true
));
$soapBody = new \SoapVar($xml, \XSD_ANYXML);
try{
$client->__soapCall('SOMEACTION', array($soapBody));
}
catch (SoapFault $exception) {
echo $exception->getMessage();
}
The xml
variable contains XML code that I know is correct. It has been tested both on SoapUI (where I had to provide my keys and password) and an online testing service my provider has made available. This means that the data being sent is 100% correct.
However, my PHP code ends up with "Internal Error". I am assuming it has to do with the lack of certificates and the like. I am not sure if there is a way to get more information from the response but there is no documentation about the said error.
I have been toying with several options and keystores, private keys and certificates in several formats without getting any positive result. I think it all has to do with the fact that the correct header is not being sent.
Thanks a lot.