HTTP request for a SOAP web service using WS-Security 1.0 with a digital certificate for authentication
This article will
- Explain the format and content of an HTTP request for a SOAP web service using WS-Security 1.0 with a digital certificate for authentication
- Describe the steps for writing code that loads the certificate and private key, constructs the XML, signs the XML, and then constructs the HTTP request and sends it.
- Provides links to examples that demonstrate the steps explained in #2.
Format and Content of the HTTP SOAP Request
Here’s an example of an HTTP request for a SOAP web service using WS-Security 1.0 with a digital certificate for authentication. The request includes the necessary headers and a SOAP envelope containing a signed message using XML Signature to authenticate with the web service.
HTTP Request Format:
POST /MyWebService HTTP/1.1 Host: www.example.com Content-Type: text/xml; charset=utf-8 Content-Length: [length] SOAPAction: "http://www.example.com/MyWebService"
SOAP Request Body:
<?xml version="1.0" encoding="UTF8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.example.com/webservice/"> <SOAP-ENV:Header> <wsse:Security xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 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" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" SOAP-ENV:mustUnderstand="1"> <wsse:BinarySecurityToken 1 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#X509" wsu:Id="x509cert00">MIIChDCCAe2....</wsse:BinarySecurityToken> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <c14n:InclusiveNamespaces xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds wsu xenc SOAP-ENV "/> </ds:CanonicalizationMethod> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#TheBody"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> <c14n:InclusiveNamespaces xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsu SOAP-ENV "/> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 2 <ds:DigestValue>QORZEA+gpafluShspHxhrjaFlXE=</ds:DigestValue> 3 </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>drDH0XE....3pw=</ds:SignatureValue> <ds:KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI="#x509cert00" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509"/> 5 </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> </wsse:Security> </SOAP-ENV:Header> <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody"> <!-- Your request data goes here --> <web:MyRequest> <web:Parameter>MyValue</web:Parameter> </web:MyRequest> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Explanation of the Key Sections:
- HTTP Headers:
- “POST”: The HTTP method to invoke the SOAP service.
- “SOAPAction”: Specifies the intent of the SOAP request, defined by the web service.
- “Content-Type”: Indicates that the body is a SOAP XML message.
- SOAP Envelope:
- “soapenv:Envelope”: The outer wrapper for the SOAP message.
- “soapenv:Header”: Contains WS-Security information.
- WS-Security Header (“wsse:Security”):
- BinarySecurityToken: Encodes the X.509 certificate (base64-encoded) of the client. This is used to verify the identity of the client. The certificate is included in the SOAP header.
- Signature: Provides the XML Signature that signs the SOAP body. The “SignedInfo” block includes the canonicalization and digest methods, while “SignatureValue” contains the result of signing the SOAP body.
- SecurityTokenReference: Refers to the certificate (with “URI=”#X509Token”) used for the digital signature.
- SOAP Body:
- Contains the actual request (“web:MyRequest”) that the client sends to the web service, including any parameters or data.
- The “wsu:Id=”Body” attribute is used to uniquely identify the body so that it can be referenced and signed.
Key Components:
- WS-Security 1.0: A standard for securing SOAP messages, which includes mechanisms like digital signatures and encryption.
- X.509 Certificate: A public key certificate used for authentication and ensuring that the message has been signed by the client’s private key.
- XML Signature: Signs the content of the SOAP message to ensure integrity and authenticity.
- Nonce and Timestamp (Optional): Often used in WS-Security for replay attack protection. This example doesn’t include them, but they can be added using “wsse:Nonce” and “wsu:Timestamp”.
Coding Steps to Construct and Send a Signed SOAP Request
1. Load the Certificate and it’s Private Key.
Chilkat provides many ways to load a certificate and private key into the Chilkat.Cert object. Here are some (but not all) methods that Chilkat supports:
- Load from a .pfx/.p12 file by calling Chilkat.Cert.LoadPfxFile. Note: The same methods exist in all of the programming languages supported by Chilkat and on all supported operating systems, unless it obviously doesn’t make sense, such as the method for loading from the Windows Certificate Stores, or loading from the MacOS Keychain.
- Load from a USB token or smartcard by calling Chilkat.Cert.LoadFromSmartcard.
- Load from the Windows Certificate Store by calling a method such as Chilkat.Cert.LoadByCommonName.
- Load from the MacOS or iOS Keychain by also calling Chilkat.Cert.LoadByCommonName or other methods. (This is new in Chilkat v10.0.0 and will be documented in more detail very soon.)
- Use Chilkat’s lower-level PKCS11 or ScMinidriver classes to load from a USB token or smartcard.
- Load the certificate and private key from separate PEM files (or other formats) and then link the certificate to the private key by calling Cert.SetPrivateKey
2. Build the SOAP XML that will be signed.
This is the SOAP XML without the <ds:Signature> … </ds:Signature> Chilkat’s XmlDSigGen class will add the ds:Signature. For the above XML, you’ll want to build this pre-signed XML:
<?xml version="1.0" encoding="UTF8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.example.com/webservice/"> <SOAP-ENV:Header> <wsse:Security xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 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" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" SOAP-ENV:mustUnderstand="1"> <wsse:BinarySecurityToken 1 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#X509" wsu:Id="x509cert00">MIIChDC....</wsse:BinarySecurityToken> </wsse:Security> </SOAP-ENV:Header> <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody"> <!-- Your request data goes here --> <web:MyRequest> <web:Parameter>MyValue</web:Parameter> </web:MyRequest> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
You can generate code that builds the pre-signed XML by copying the XML into Chilkat’s online code generator at https://tools.chilkat.io/xmlCreate For example, if C# is chosen, the code generated for the above XML is:
Chilkat.Xml xml = new Chilkat.Xml(); xml.Tag = "SOAP-ENV:Envelope"; xml.AddAttribute("xmlns:SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/"); xml.AddAttribute("xmlns:web","http://www.example.com/webservice/"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",true,"xmlns:ds","http://www.w3.org/2000/09/xmldsig#"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",true,"xmlns:wsse","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",true,"xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",true,"xmlns:xenc","http://www.w3.org/2001/04/xmlenc#"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",true,"SOAP-ENV:mustUnderstand","1"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security|wsse:BinarySecurityToken",true,"A1",""); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security|wsse:BinarySecurityToken",true,"EncodingType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security|wsse:BinarySecurityToken",true,"ValueType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509"); xml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security|wsse:BinarySecurityToken",true,"wsu:Id","x509cert00"); xml.UpdateChildContent("SOAP-ENV:Header|wsse:Security|wsse:BinarySecurityToken","BinarySecurityToken_Base64Binary_Content"); xml.UpdateAttrAt("SOAP-ENV:Body",true,"xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); xml.UpdateAttrAt("SOAP-ENV:Body",true,"wsu:Id","TheBody"); xml.UpdateChildContent("SOAP-ENV:Body|web:MyRequest|web:Parameter","MyValue");
The BinarySecurityToken_Base64Binary_Content will contain the base64 encoding of the signing certificate, which is obtained by calling Cert.GetEncoded
3. Write Code using Chilkat.XmlDSigGen to Add the ds:Signature
This is easy because you can use another Chilkat online code generation tool to do it. Go to the following online tool: https://tools.chilkat.io/xmlDsigGen Copy the above fully-signed XML (which is just a representation of the desired format of the signed XML) into the online tool, choose your programming language and a few other options, and generate. The signed XML is what will be contained in the body of the HTTP POST to be sent. The next step is to generate the code for creating the HTTP POST and sending it. You can do it by copying the following raw HTTP request into yet another Chilkat online tool to generate the code:
POST /MyWebService HTTP/1.1
Host: www.example.com
Content-Type: text/xml; charset=utf-8
Content-Length: [length]
SOAPAction: “http://www.example.com/MyWebService”<dummy>SOAP XML GOES IN HERE</dummy>
Use the Chilkat online tool at https://tools.chilkat.io/httpRequestToCode to generate source code from a raw HTTP request. You’ll replace the code that generates the dummy body with the code generated in step2.
Putting it All Together
Here are links to examples where we’ve done each of the above steps to build, sign, and send the SOAP request as shown at the top of this page.