1

Due to some very specific requirements for submitting messages to the IRS, I am having to use a custom encoding to create an MTOM message. Problem is, after that encoder is done processing, the message is no longer XML since it has to create the boundaries and headers for the attachment.

This is very problematic because this custom encoding is executed PRIOR to the endpoint behavior I have configured to sign the outbound message with our X509 cert. Configuration here:

<behaviors>
  <endpointBehaviors>
    <behavior name="SigningBehavior">
      <clientCredentials>
        <clientCertificate findValue="serial goes here" x509FindType="FindBySerialNumber"
          storeLocation="CurrentUser" storeName="My" />
        <serviceCertificate>
          <defaultCertificate findValue="serial goes here" x509FindType="FindBySerialNumber"
          storeLocation="CurrentUser" storeName="My" />
          <authentication certificateValidationMode="PeerTrust"/>
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>

Is there a way to have the WCF client sign and add the WS-security header BEFORE the custom encoding is executed?

Bon
  • 1,083
  • 12
  • 23

1 Answers1

0

You should check with this blogger http://webservices20.blogspot.com/2011/01/xml-digital-signature-signing-keyinfo.html. He is an expert in WCF.

I still haven't reached your point. Working on including MTOM. How did you add the payload as an MTOM attachment? I was using mtomMessageEncoding messageVersion="Soap11". Then I realized IRS needs GZip encoding.

user2596613
  • 67
  • 1
  • 9
  • Oh its not easy. I customized the gzipMessageEncoding and made it reference the Microsoft Austria implementation of SOAP with Attachments as an innerMessageEncoding instead of the WCF built in MTOM encoding. That way I know ahead of time what id values will be used for the attachment and boundary, allowing me to properly set the HTTP Headers (specifically the Content-Type header). I found out much later than is desirable that you cannot modify or add HTTP headers any time after your message has entered the WCF pipeline. So they have to be set ahead of time. Next message I will detail MTOM more – Bon Feb 17 '16 at 18:12
  • Now, inside the SWA encoding Write method, that is where I'm doing my signing and making other manipulations. Signing comes very last, of course. Needed to replace the inline attachment BulkExchangeFile contents with the xop:Include with the href attribute matching the id of the MTOM attachment. Then, after that and I do the x509 signing, it goes back up to the outer gzip encoding, and then down the wire to the IRS. – Bon Feb 17 '16 at 18:15
  • I'm stuck at invalid WS-header now after having good success using the SignedXml class to load the entire SOAP message, referencing the 3 header ids, and am getting an ALMOST valid signature element from it. But it isn't using the SecurityTokenReference as IRS seems to require. Instead it is using the likewise valid (according to W3C) X509Data and X509Certificate elements inside of the KeyInfo element. – Bon Feb 17 '16 at 18:18
  • Also, I had already checked out that blogger (and every other possible search result on google lol). Unfortunately none of his solutions will work for us because the MTOM encoding completely destroys any notion of an XML document in the outbound message. So the built-in X509 signing utilities in WCF are useless for this case. – Bon Feb 17 '16 at 18:21
  • Thanks for the details. I guess this is the implementation you are talking about https://code.msdn.microsoft.com/Send-Soap-with-Attachments-3784e5f6. – user2596613 Feb 17 '16 at 18:47
  • That isn't feasible for production use. So no reason to bother trying it. Ended up just using the SignedXml class to generate my signed elements manually and manipulating the outbound xml in the encoder right before it converts it to MTOM. – Bon Feb 22 '16 at 16:46
  • Yes that is a DEV solution. Trying to figure out the correct XML format. – user2596613 Feb 22 '16 at 17:04
  • I see that you have started using linq to xml to create soap. Are you using linq to create every element of envelope and sign with certificate? What soap envelope schema did you use to create the message? – user2596613 Feb 29 '16 at 18:40
  • Bon could you review my soap request posted here http://stackoverflow.com/q/35855848/2596613. Getting boundary error message. Appreciate it. – user2596613 Mar 08 '16 at 15:53
  • @Bon I am using SignedXML for signing and then regenerating SignatureValue for SignedInfo with prefix ds. Verification of the signing passes with cert public key. Still get WS Security header. Are you using XmlDocument.Save to write xml to stream and does you header have wsa:action element? – user2596613 Mar 14 '16 at 21:01
  • I'm converting the GetXml() XmlDocument into an XElement, altering the SignatureValue in there, and then inserting that into the Security node of my root XElement soapEnvelope object. I then serialize the envelope and sandwich it between the MTOM delimiters and the attachment. – Bon Mar 15 '16 at 00:49
  • Thanks @Bon. Still no luck in clearing WS Security header. – user2596613 Mar 16 '16 at 17:52
  • Make sure you're handling whitespace consistently. I make sure all my XmlDocument usages have IgnoreWhitespace set to true. – Bon Mar 16 '16 at 17:56
  • Yes no whitespace and I am also removing BOM character. – user2596613 Mar 16 '16 at 21:08
  • @Bon I am looking at today's webinar presentation. They mention WS-Security header error and list below causes. - Digest mismatch caused when the SOAP message changes after being signed. - The KeyInfo is not in the expected KeyIdentifier format. - The certificate is not Base64 encoded properly. - The certificate does not follow the x.509 standard structure. For base64 encoding I am doing this `var certToken = new X509SecurityToken(X509Certificate2); var token = Convert.ToBase64String(certToken.Certificate.RawData);' Is this correct? – user2596613 Mar 22 '16 at 18:38
  • Yes, that is correct. That is how I am also generating my BinarySecurityToken. – Bon Mar 23 '16 at 05:49
  • Thanks @Bon. Do you know where ASID(id provided after a certificate is uploaded) should be used? Or do we have to link certificate to an application package? – user2596613 Mar 23 '16 at 21:38
  • It turns out you actually don't need the ASID at all. It is just a reference number for their internal usage and they are able to identify the certificate via your TCC and KeyInfo element, it seems. – Bon Mar 23 '16 at 22:08