Search code examples
wcfsoapwcf-clientx509certificatews-security

How to make WCF Client conform to specific WS-Security


I must make my WCF Client consume a web service (IBM DataPower) and sign/encrypt the request using Web Services Security X.509 Certificate Token Profile 1.1 OASIS Standard Specification, 1 February 2006.

So far I have created a custom binding and "think" I am working along the right lines:

Updated to reflect latest attempt

Private Function CreateCustomBinding() As Channels.Binding

    Dim asbe As New Channels.AsymmetricSecurityBindingElement

    asbe.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10

    asbe.InitiatorTokenParameters = New ServiceModel.Security.Tokens.X509SecurityTokenParameters
    asbe.RecipientTokenParameters = New ServiceModel.Security.Tokens.X509SecurityTokenParameters

    asbe.MessageProtectionOrder = Security.MessageProtectionOrder.EncryptBeforeSign

    asbe.SecurityHeaderLayout = SecurityHeaderLayout.Strict

    asbe.IncludeTimestamp = True
    asbe.SetKeyDerivation(False)

    asbe.DefaultAlgorithmSuite = Security.SecurityAlgorithmSuite.Basic128Rsa15  'By default, AES-128 is used as the encryption algorithm.

    'Add the elements to the custom binding
    Dim myBinding As New CustomBinding

    'element order is important - see http://msdn.microsoft.com/en-us/library/ms733893(v=vs.90).aspx

    'Protocol Binding Elements (security)
    myBinding.Elements.Add(asbe)

    'Encoding Binding Element  
    myBinding.Elements.Add(New TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, System.Text.Encoding.UTF8))

    'Transport Binding Element
    Dim httpsBindingElement As New HttpsTransportBindingElement()
    httpsBindingElement.RequireClientCertificate = True
    myBinding.Elements.Add(httpsBindingElement)

    Return myBinding

End Function

Then use this binding like so:

Dim epi As EndpointIdentity = EndpointIdentity.CreateDnsIdentity("xgtwsqa.theirdomain.com")

Dim epuri As Uri = New Uri("https://xgtwqa.theirdomain.com/5067/ProcessRepairOrder")
Dim ea As New EndpointAddress(epuri, epi, New AddressHeaderCollection)

Dim myBinding As Binding = GetCustomBinding2()

' Create the client. 
Dim starClientProxy As New wcfStarServiceProxy.starTransportPortTypesClient(myBinding, ea)

' Specify a certificate to use for authenticating the client.
starClientProxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "*.mydomain.org.uk")

starClientProxy.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.AddressBook, X509FindType.FindBySubjectName, "xgtwsqa.theirdomain.com")

'starClientProxy.ClientCredentials.ServiceCertificate.SetScopedCertificate(StoreLocation.CurrentUser, StoreName.AddressBook, X509FindType.FindBySubjectName, "xgtwsqa.theirdomain.com", New Uri("https://xgtwqa.thedomain.com/5067/ProcessRepairOrder"))

' Begin using the client.
Dim response As wcfStarServiceProxy.AcknowledgeRepairOrderPayload = starClientProxy.ProcessMessage(payload)

Would someone either tell me what else I need to configure in the binding (I am pretty sure the binding method isn't quite right) or provide me with the code I need?

The above produces the following SOAP:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

  <s:Header>
    <a:Action s:mustUnderstand="1" u:Id="_3">
    http://www.starstandards.org/webservices/2009/transport/operations/ProcessMessage</a:Action>
    <a:MessageID u:Id="_4">
    urn:uuid:c2acbb72-49c2-465b-b177-e806494cdef7</a:MessageID>
    <a:ReplyTo u:Id="_5">
      <a:Address>
      http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1" u:Id="_6">
    https://xgtwqa.theirdomain.com/5067/ProcessRepairOrder</a:To>
    <o:Security s:mustUnderstand="1"
    xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">

      <u:Timestamp u:Id="uuid-b8d302ff-a098-42bb-afc6-694e647c23b0-1">

        <u:Created>2012-06-01T14:35:18.781Z</u:Created>
        <u:Expires>2012-06-01T14:40:18.781Z</u:Expires>
      </u:Timestamp>
      <o:BinarySecurityToken u:Id="uuid-7f9c9673-ae43-4fb5-8510-03cc4b98fa93-2"
      ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
      EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
      removed</o:BinarySecurityToken>
      <o:BinarySecurityToken u:Id="uuid-7f9c9673-ae43-4fb5-8510-03cc4b98fa93-1"
      ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
      EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
      removed</o:BinarySecurityToken>
      <e:EncryptedKey Id="_0"
      xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
            URI="#uuid-7f9c9673-ae43-4fb5-8510-03cc4b98fa93-1" />
          </o:SecurityTokenReference>
        </KeyInfo>
        <e:CipherData>
          <e:CipherValue>
          removed</e:CipherValue>
        </e:CipherData>
      </e:EncryptedKey>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
          <Reference URI="#_2">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
          <Reference URI="#_3">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
          <Reference URI="#_4">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
          <Reference URI="#_5">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
          <Reference URI="#_6">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
          <Reference URI="#uuid-b8d302ff-a098-42bb-afc6-694e647c23b0-1">

            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removed</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>
        removed</SignatureValue>
        <KeyInfo>
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
            URI="#uuid-7f9c9673-ae43-4fb5-8510-03cc4b98fa93-2" />
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
      <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:DataReference URI="#_1" />
      </e:ReferenceList>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_2"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <e:EncryptedData Id="_1"
    Type="http://www.w3.org/2001/04/xmlenc#Content"
    xmlns:e="http://www.w3.org/2001/04/xmlenc#">
      <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
      </e:EncryptionMethod>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <o:Reference URI="#_0"></o:Reference>
        </o:SecurityTokenReference>
      </KeyInfo>
      <e:CipherData>
        <e:CipherValue>removed</e:CipherValue>
      </e:CipherData>
    </e:EncryptedData>
  </s:Body>
</s:Envelope>

This is a sample of the SOAP I am expected to send:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:star="http://www.starstandard.org/STAR/5"
xmlns:tran="http://www.starstandards.org/webservices/2005/10/transport">

  <soap:Header>
    <wsa:To>urn:removed/star/services/v1/GetConditionCodes</wsa:To>
    <wsa:Action>
    http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage</wsa:Action>
    <wsa:MessageID>
    ef67ec85-d5c7-4669-b1a6-440ec2fe938b</wsa:MessageID>

    <tns:RespondTo xmlns:tns="urn:removed/soa/routing/v1.0">
      <tns:Endpoint>
      https://b2b-test.mydomain.com/Async/removed/StarWebService.ashx</tns:Endpoint>
    </tns:RespondTo>
    <tran:payloadManifest>
      <tran:manifest contentID="A0"
      namespaceURI="http://www.starstandard.org/STAR/5"
      element="GetStandardCodes" version="5.2.4" />
    </tran:payloadManifest>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    mustUnderstand="1">
      <u:Timestamp xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
      Id="timestamp" u:Id="timestamp">
        <u:Created>2012-05-30T16:39:39Z</u:Created>
        <u:Expires>2012-05-30T16:44:39Z</u:Expires>
      </u:Timestamp>
      <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
      ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
      EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
      wsu:Id="binary_security_token">
      removed</wsse:BinarySecurityToken>
      <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <wsse:SecurityTokenReference>
            <wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
            EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
            4qEuhS3IWjReFLSSCOcVoN6Ywzo=</wsse:KeyIdentifier>
          </wsse:SecurityTokenReference>
        </KeyInfo>
        <CipherData>
          <CipherValue>
          removed</CipherValue>
        </CipherData>
        <ReferenceList>
          <DataReference URI="#encrypt" />
        </ReferenceList>
      </EncryptedKey>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
          <Reference URI="#body">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removeddigestvalue</DigestValue>
          </Reference>
          <Reference URI="#timestamp">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>removeddigestvalue</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>
        removed</SignatureValue>
        <KeyInfo>
          <wsse:SecurityTokenReference>
            <wsse:Reference URI="#binary_security_token"
            ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
          </wsse:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </wsse:Security>
  </soap:Header>
  <soap:Body xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  id="body" u:Id="body">
    <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"
    Id="encrypt" Type="http://www.w3.org/2001/04/xmlenc#Content">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
      <CipherData>
        <CipherValue>
        removed</CipherValue>
      </CipherData>
    </EncryptedData>
  </soap:Body>
</soap:Envelope>

Solution

  • try to use this config:

          <customBinding>
                <binding name="NewBinding0">
                    <textMessageEncoding messageVersion="Soap11WSAddressing10" />
                    <security authenticationMode="MutualCertificate" messageProtectionOrder="SignBeforeEncrypt"
                        messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
                        <secureConversationBootstrap />
                    </security>
                    <httpTransport />
                </binding>
            </customBinding>
        </bindings>
    

    if you want to use code the main difference is the use of WSSEcurity10 in the version (even though you need 11, this is compatible) and the messageProtectionOrder (which is why you only see encryption and not signature).

    this may require further fine tuning, let me know the progress.

    since you use code also set:

    asbe.RecipientTokenParameters.X509ReferenceStyle=X509KeyIdentifierClauseType .SubjectKeyIdentifier
    

    and:

    asbe.RecipientTokenParameters.InclusionMode = SecurityTokenInclusionMode.Never