title: WCF Client consuming WS-Security webservice
body: <p>I managed to consume a java based web service (third party) with WS-Security 1.1 protocol. The web service needs only to be signed over a x509 certificate, not encrypted.
  But I'm getting this error:</p>
  
  <blockquote>
    <p>The signature confirmation elements cannot occur after the primary signature.</p>
  </blockquote>
  
  <p>The captured server response package looks like this:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
      &lt;soapenv:Header&gt;
          &lt;wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true"&gt;
              &lt;ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-501"&gt;
                  &lt;ds:SignedInfo&gt;
                      &lt;ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
                      &lt;ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
                      &lt;ds:Reference URI="#id-502"&gt;
                          &lt;ds:Transforms&gt;
                              &lt;ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
                          &lt;/ds:Transforms&gt;
                          &lt;ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
                          &lt;ds:DigestValue&gt;...&lt;/ds:DigestValue&gt;
                      &lt;/ds:Reference&gt;
                      &lt;ds:Reference URI="#SigConf-500"&gt;
                          &lt;ds:Transforms&gt;
                              &lt;ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
                          &lt;/ds:Transforms&gt;
                          &lt;ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
                          &lt;ds:DigestValue&gt;...&lt;/ds:DigestValue&gt;
                      &lt;/ds:Reference&gt;
                  &lt;/ds:SignedInfo&gt;
                  &lt;ds:SignatureValue&gt;
                  ...
                  &lt;/ds:SignatureValue&gt;
                  &lt;ds:KeyInfo Id="KeyId-..."&gt;
                      &lt;wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-..."&gt;
                          &lt;ds:X509Data&gt;
                              &lt;ds:X509IssuerSerial&gt;
                                  &lt;ds:X509IssuerName&gt;CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB&lt;/ds:X509IssuerName&gt;
  
                                  &lt;ds:X509SerialNumber&gt;...&lt;/ds:X509SerialNumber&gt;
                              &lt;/ds:X509IssuerSerial&gt;
                          &lt;/ds:X509Data&gt;
                      &lt;/wsse:SecurityTokenReference&gt;
                  &lt;/ds:KeyInfo&gt;
              &lt;/ds:Signature&gt;
              &lt;wsse11:SignatureConfirmation xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Value="..." wsu:Id="SigConf-500"/&gt;
          &lt;/wsse:Security&gt;
      &lt;/soapenv:Header&gt;
      &lt;soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-502"&gt;
          &lt;altaClienteResponse xmlns="..."&gt;
              &lt;altaClienteReturn&gt;
                  &lt;codigoError&gt;7&lt;/codigoError&gt;
                  &lt;descripcionError&gt;El código de banco no es válido.&lt;/descripcionError&gt;
                  &lt;idTransaccion xsi:nil="true"/&gt;
              &lt;/altaClienteReturn&gt;
          &lt;/altaClienteResponse&gt;
      &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
  </code></pre>
  
  <p>The server is responding what it should but my app seems not to be interpreting it correctly. It seems that the <code>&lt;wsse11:SignatureConfirmation .../&gt;</code> tag must be before <code>&lt;ds:Signature&gt;&lt;/ds:Signature&gt;</code> tag. </p>
  
  <p>I couldn't find any reference to a order standard of this.</p>
  
  <p>EDIT: Adding my code.</p>
  
  <pre><code>try
  {
      var certificate = new X509Certificate2(@"C:\Users\...\cert.pfx", PassKeyStore);
  
      var binding = new CustomBinding();
  
      var security = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
  
      security.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters
      {
          InclusionMode = SecurityTokenInclusionMode.Never,
          ReferenceStyle = SecurityTokenReferenceStyle.Internal,
      });
  
      security.RecipientTokenParameters.InclusionMode = SecurityTokenInclusionMode.Never;
      security.RecipientTokenParameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
  
      security.MessageSecurityVersion =
          MessageSecurityVersion.
              WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
      security.IncludeTimestamp = false;
      security.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.EncryptBeforeSign;    
  
      security.RequireSignatureConfirmation = true;
      security.AllowSerializedSigningTokenOnReply = true;   
  
      binding.Elements.Add(security);
      binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
      binding.Elements.Add(new HttpsTransportBindingElement());    
  
      var client = new SistarbancService.WsMediosPagoClient(binding, new EndpointAddress(new Uri(UrlSistarbanc), new DnsEndpointIdentity("..."), new AddressHeaderCollection()));    
  
      client.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2("C:\\Users\\...\\servidor.cer");
      client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
          System.ServiceModel.Security.X509CertificateValidationMode.None;
      client.ClientCredentials.ClientCertificate.Certificate = certificate;
  
      client.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
  
      var response = await client.altaClienteAsync("XXX", "0", "0", "0", "0", "0");
  }
  catch (Exception ex)
  {
  
  }
  </code></pre>