0

I have a ASMX web service (SOAP 1.1) that requires to sign all SOAP requests with certificate (private key) using WS-Security.

When the ASMX service receives the request, it will authenticate it using the public key of the certificate. After the operation is done, the response sent back to the client will not be signed!

That's the security requirements...

I've created the proxy via 'Add Service Reference' and the client's app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint
        name="endpoint1"
        address="http://1.1.1.1/Test.asmx"
        binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_ITest"
        behaviorConfiguration="TestBehavior"
        contract="ITest" >
      </endpoint>
    </client>

    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_ITest">
          <security mode="Message">
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <endpointBehaviors>
        <behavior name="TestBehavior">
          <clientCredentials>
            <clientCertificate storeLocation="LocalMachine" storeName="My" 
                               x509FindType="FindByThumbprint" findValue="xxxxxxxxxxxxxxx" />

          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

According to the scenario I've described:

  1. Am I using the correct binding?

  2. clientCredentialType value should be 'Certificate' or 'None' ?

  3. The tag 'serviceCertificate' is needed ?

    4.What is the correct configuration for my scenario?

If you know some useful links that could be suitable for my scenario, please supply them.

Thanks in advance :)




EDIT #1:

Request

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    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">
    <soap:Header>   
        <wsa:Action wsu:Id="Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800">XXXXXXXXXXX</wsa:Action>
        <wsa:MessageID wsu:Id="Id-3beeb885-12a4-4b65-b14c-0tmj6ad21855">YYYYYYYYYY</wsa:MessageID>
        <wsa:ReplyTo wsu:Id="Id-10c46143-cb53-4a8e-9e83-ef374e40aa54">
            <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
        </wsa:ReplyTo>
        <wsa:To wsu:Id="Id-17c40943-cs53-4a8e-9e83-ef374e40ab70">
            <wsa:Address>http://.../TestOperation</wsa:Address>
        </wsa:To>
        <wsse:Security soap:mustUnderstand="1" >
            <wsu:Timestamp wsu:Id="Timestamp-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685">
                <wsu:Created wsu:Id="Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800">2002-08-22T00:26:15Z</wsu:Created>
                <wsu:Expires wsu:Id="Id-10c46143-cb53-4a8e-9e83-ef374e40aa54">2002-08-22T00:31:15Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:BinarySecurityToken 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" 
                                      xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
                                      wsu:Id="SecurityToken-e00c8062-83d2-4f04-88fc-996218e7bb3d">MIICeDCC...kE9</wsse:BinarySecurityToken>
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                <SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
                    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
                    <Reference URI="#Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>wRUq.........</DigestValue>
                    </Reference>
                    <Reference URI="#Id-3beeb885-12a4-4b65-b14c-0tmj6ad21855">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>8gIo.........</DigestValue>
                    </Reference>
                    <Reference URI="#Id-10c46143-cb53-4a8e-9e83-ef374e40aa54">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>zx4h.........</DigestValue>
                    </Reference>
                    <Reference URI="#Id-17c40943-cs53-4a8e-9e83-ef374e40ab70">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>UjdN.........</DigestValue>
                    </Reference>
                    <Reference URI="#Timestamp-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>34ff.........</DigestValue>
                    </Reference>
                    <Reference URI="#Id-f10674fd-b999-47c9-9568-c11fa5e5405b"">
                        <Transforms>
                            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </Transforms>
                        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                        <DigestValue>ss67.........</DigestValue>
                    </Reference>
                </SignedInfo>
                <SignatureValue>tBSsaZi........</SignatureValue>
                <KeyInfo>
                    <wsse:SecurityTokenReference>
                        <wsse:Reference URI="#SecurityToken-e00c8062-83d2-4f04-88fc-996218e7bb3d" 
                                        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 wsu:Id="Id-f10674fd-b999-47c9-9568-c11fa5e5405b">
        ...
    </soap:Body>
</soap:Envelope>

Respose:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    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">
  <soap:Header>
    <wsa:Action>http://.../TestOperationResponse</wsa:Action>
    <wsa:MessageID>YYYYYYYYYY</wsa:MessageID>
    <wsa:RelatesTo>WWWWWWWWWW</wsa:RelatesTo>
    <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
    <wsse:Security>
      <wsu:Timestamp wsu:Id="Timestamp-c0kjk2d4-o83d-4fa5-abfa-bd485afdjj80">
        <wsu:Created>2002-08-22T00:26:15Z</wsu:Created>
        <wsu:Expires>2002-08-22T00:31:15Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <Response>
      ...
    </Response>
  </soap:Body>
</soap:Envelope>




EDIT #2:

The generated request:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <soap:Header>   
        <a:Action soap:mustUnderstand="1" u:Id="_2">XXXXXXXXXXX</a:Action>
        <a:MessageID u:Id="_3">YYYYYYYYYY</a:MessageID>
        <a:ReplyTo u:Id="_4">
            <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
        </a:ReplyTo>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uID...</VsDebuggerCausalityData>
        <a:To soap:mustUnderstand="1" u:Id="_5">
            <a:Address>http://1.1.1.1/Test.asmx</a:Address>
        </a:To>
        <o:Security soap: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-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685-1">
                <u:Created>2002-08-22T00:26:15Z</u:Created>
                <u:Expires>2002-08-22T00:31:15Z</u:Expires>
            </u:Timestamp>
            <o:BinarySecurityToken u:Id="uuid-e00c8062-83d2-4f04-88fc-996218e7bb3d-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">MIICeDCC...kE9</o:BinarySecurityToken>
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                <SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
                    <Reference URI="#_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>wRUq.........</DigestValue>
                    </Reference>
                    <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>8gIo.........</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>zx4h.........</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>UjdN.........</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>34ff.........</DigestValue>
                    </Reference>
                    <Reference URI="#uuid-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685-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>ss67.........</DigestValue>
                    </Reference>
                </SignedInfo>
                <SignatureValue>tBSsaZi........</SignatureValue>
                <KeyInfo>
                    <o:SecurityTokenReference>
                        <o:Reference URI="#uuid-e00c8062-83d2-4f04-88fc-996218e7bb3d-2" 
                                        ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
                    </o:SecurityTokenReference>
                </KeyInfo>
            </Signature>
        </o:Security>
    </soap:Header>
    <soap:Body u:Id="_1">
        ...
    </soap:Body>
</soap:Envelope>

Issues with this request are:

  1. Id format: Id="Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800" (asmx proxy) VS Id="_2" (WCF proxy)
  2. 'VsDebuggerCausalityData' tag presence. How do I get rid of it?
  3. Timestamp Id format: Id="Timestamp-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685" (asmx proxy) VS Id="uuid-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685-1" (WCF proxy)
  4. 'Created' and 'Expires' tags in Timestamp doesn't have Id attribute.
  5. BinarySecurityToken Id format: Id="SecurityToken-e00c8062-83d2-4f04-88fc-996218e7bb3d" (asmx proxy) VS Id="uuid-e00c8062-83d2-4f04-88fc-996218e7bb3d-2" (WCF proxy)


The fault I get when I make a call to the ASMX service:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"">
  <soap:Header>
    <wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/addressing/fault</wsa:Action>
    <wsa:MessageID>YYYYYYYYYY</wsa:MessageID>
    <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
  </soap:Header>
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>
          System.Web.Services.Protocols.SoapHeaderException: Server unavailable, please try later ---> System.ApplicationException: WSE842: The service pipeline could not be created. ---> System.ApplicationException: WSE2012: X509TokenProvider is unable to provide an X.509 token. There are multiple certificates store that match the find value of 'xxx'.
          at Microsoft.Web.Services3.Design.X509TokenProvider.CreateToken(StoreLocation location, StoreName storeName, String findValue, X509FindType findType)
          at Microsoft.Web.Services3.Design.X509TokenProvider.GetToken()
          at Microsoft.Web.Services3.Design.MutualCertificate10Assertion.ServiceInputFilter..ctor(MutualCertificate10Assertion assertion)
          at Microsoft.Web.Services3.Design.MutualCertificate11Assertion.CreateServiceInputFilter(FilterCreationContext context)
          at Microsoft.Web.Services3.Design.Policy.CreateServicePipeline(PipelineCreationContext context)
          at Microsoft.Web.Services3.PolicyAttribute.Microsoft.Web.Services3.IPipelineProvider.CreateServicePipeline(PipelineCreationContext context)
          at Microsoft.Web.Services3.Pipeline.TryCreate(Type type, Boolean forClient)
          at Microsoft.Web.Services3.WseProtocol.CreateProtocolPipeline()
          at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
          at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
          at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)
          --- End of inner exception stack trace ---
          --- End of inner exception stack trace ---
      </faultstring>
      <faultfactor>http://1.1.1.1/Test.asmx</faultfactor>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

I assume the problem is at the server, because the 'xxx' findValue is associated with the server and not with my client certificate. How can I fix this?

Sash
  • 493
  • 2
  • 10
  • 19

1 Answers1

1

Try this binding:

            <customBinding>
                <binding name="NewBinding0">
                    <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
                    <security authenticationMode="MutualCertificate">
                        <secureConversationBootstrap />
                    </security>
                    <httpTransport />
                </binding>
            </customBinding>

you will need to define both client and server certificates on the wcf proxy, if you do not know the server cert just define a dummy one. you also need to change protection level for your proxy such that it does not encrypt the body:

[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.SimpleServiceSoap", ProtectionLevel=System.Net.Security.ProtectionLevel.Sign)]

This post summaries a few other issues you may encounter.

Yaron Naveh
  • 23,560
  • 32
  • 103
  • 158
  • Thank you very much! The ASMX service doesn't use a certificate to sign the responses to its clients. So, what do you mean when you write "just define a dummy one" ? – Sash Jun 24 '13 at 15:21
  • 1
    In the WCF proxy you can configure both client and server certificate. You do not have a server certificate but in the current settings wcf will require something to put in it (it will not be used). So just configure the same certificate as the client certificate (or any otehr certificate - it will not be used). You configure this on your client proxy, not related to server – Yaron Naveh Jun 24 '13 at 15:43
  • Thanks. I've encountered Confusion 8 as described in your post... Changing the protection level of the proxy doesn't help. I know that I can change the protection level of the contract, but of course I don't have access to it. – Sash Jun 25 '13 at 06:55
  • More issues with the generated request: 1. all Ids are not in the correct format: "Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800" (the format I get is the same as in your post). 2. Timestamp Id format is incorrect, not in "Timestamp-c0cc2cd4-cb77-4fa5-abfa-bd485afd1685" format. 3. Which value should I put in the 'messageSecurityVersion' attribute ? current value is "WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" – Sash Jun 25 '13 at 07:55
  • 1
    confusion 8 - so the request is still sent encrypted? ensure you have changes the generated proxy class (Reference.cs) in the right place. add this attribute on every operation too (in the interface). ID . Timestamp ID format - nothing you can do, but this should not matter. you have the right security version. you can publish your current request so we can compare it to the expected one. also what error you get – Yaron Naveh Jun 25 '13 at 09:25
  • I resolved the encryption issue, the request is only signed. I will also publish the request in a few minutes. – Sash Jun 25 '13 at 09:41
  • I've updated the question with the generated request (with the issues) and the fault I get when I call the service. Thank you! – Sash Jun 25 '13 at 10:50
  • 1
    yes, looks like a server issue. you have previously published a working request. how did you get it? is it a request sent to the exact same server (does not seem so according the wsa:To element)? Your request looks good now. the problem is most probably that you have defined a server certificate in your server code by its subjecvt name, but your windows store has multiple certificates with this name. you need to delete some of them or refger the certificate by other identifier. – Yaron Naveh Jun 25 '13 at 14:09
  • Yes, it's the exact same server. I will check the server side. Regarding the issues with the request - it will not affect the processing of the request at the server? – Sash Jun 25 '13 at 14:13
  • 1
    can you send me the full request (without cutting confidential parts) in an email? the request only contains the public key not the private so in general this should not be a problem. I need both the working and the failing exact requests – Yaron Naveh Jun 25 '13 at 14:25
  • Sorry, it's not possible. I also noticed that the 'Created' and 'Expires' are my time minus 3 hours, what means that the security token already expired. How can I change it? – Sash Jun 25 '13 at 14:48
  • 1
    this is a UTC date, not a problem. if this was the problem the server would say it. the server clearly complains about certificates. double check you send working and non working requests to the same server. check in the messages if the values are identical in the elements wsa:Action (a:Action), wsa:To (a:To) and wsse:BinarySecurityToken. – Yaron Naveh Jun 25 '13 at 14:55
  • I changed the server and I'm sending requests to the same service, and I get: WSE529: The security token SecurityToken-..... has already expired. – Sash Jun 25 '13 at 15:01
  • 1
    check the clock (+timezone+daylight setting) on the server and change the clock in your machine temporary to that hour (+time zone+daylight) to see if this is the issue. – Yaron Naveh Jun 25 '13 at 15:08
  • I checked the clock (+timezone+daylight setting) and it exactly the same in both the client and the server. I've just made a call: the Created time is 15:12 and the Expires time is 15:17, but the time on my local machine was 18:12 (the same as in the server). – Sash Jun 25 '13 at 15:13
  • 1
    on the server side the windows events log should have more details, interesting to see the error from the server prespective. you can also tune your clock 3 hours ahead so the message time is the same as server clock... though I don't expect it to matter. There are various settings in wcf custom binding to change the expiration time, but there is also a separate server policy. interesting - what hour does the working soap contain? what is its format (Z in the end means this is UTC)? – Yaron Naveh Jun 25 '13 at 15:22
  • The time in the soap request contains Z in the end. From the server perspective the exception is exactly identical as the exception I get in the client. – Sash Jun 25 '13 at 15:31
  • There is no working envelope so far. The original request sample was in our documentation. – Sash Jun 25 '13 at 15:42
  • 1
    in this case first use asmx client (.net 2.0 web services for lack of a better name) since it should be easyer to get a working envelope. then you can introduce wcf. you can also try to play with your pc hour until you find one that does not cause this exception, to see it this is really the only issue. – Yaron Naveh Jun 25 '13 at 15:51
  • Thanks. How do I use WS-Security with "old" asmx client? What code I need to write? – Sash Jun 25 '13 at 15:53
  • 1
    use the same stack you used for the server (WSE? check the version). you can publish the server config here, at this point I don't know if we can trust the working sample above since it has not been tested. ask whoever wrote the service to supply an example – Yaron Naveh Jun 25 '13 at 16:02
  • Update: I can't get the person that wrote the service, but the original request sample I provided works 100%. Still, I get the exception regarding the Timestamp. The clocks on client and server are exactly the same. – Sash Jun 26 '13 at 13:23
  • 1
    so maybe there is a regression in the service. you need a client that is working now, and compare its timestamp to yours – Yaron Naveh Jun 26 '13 at 14:07
  • Yaron, thanks a lot! Finally, the problem was solved! The security token exception was a result of expired certificate on the server side. – Sash Jun 27 '13 at 16:58