WCF client passing username token with mustUnderstand set to true

I am tasked with creating a WCF service that will be consumed by an external client. The client uses WSSE security, in particular, they pass the username token through the SOAP header.

WCF is hosted on an IIS server with SSL enabled.

At this moment, I have a semi-working prototype. The problem I'm currently facing is that the SOAP header has the mustUnderstand attribute set to 1, and this leads to the process crashing.

I would like some advice (or better yet, an example of emoticon code) on how to handle the username token in such a way as to return the correct answer when the mustUnderstand attribute is true.

Here is an example of a SOAP request that does not execute:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"> <soapenv:Header> <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:UsernameToken> <wsse:Username>TestUser</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPWD</wsse:Password> <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NzU3MjFhN2YtYTlmYS00ZWZjLTkxNjktY2ExZjlkZDEwNzE5</wsse:Nonce> <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2011-10-26T03:04:39Z</wsu:Created> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> <tem:Getstuff> <tem:Arg1>Arg1</tem:Arg1> <tem:Arg2>Arg2</tem:Arg2> </tem:Getstuff> </soapenv:Body> </soapenv:Envelope> 

If soapenv: mustUnderstand = "1" changes to soapenv: mustUnderstand = "0", then the process works.


PS: Here is the revised sample request sent by the client:

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/WService/Getstuff</Action> <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="removed" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:Username>TestUser</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPass</wsse:Password> <wsse:Nonce>2Udx78sh2y2xRJYJpZZ9+w==</wsse:Nonce> <wsu:Created>2011-09-26T19:12:48Z</wsu:Created> </wsse:UsernameToken> </Security> </s:Header> <s:Body> <Getstuff xmlns="http://tempuri.org/"> <Arg1>Arg1</Arg1> <Arg2>Arg2</Arg2> </Getstuff> </s:Body> </s:Envelope> 

I get the following response to the above requests:

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <s:Fault> <faultcode>s:MustUnderstand</faultcode> <faultstring xml:lang="en-US">The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed. This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process. Please ensure that the configuration of the client binding is consistent with the service binding.</faultstring> </s:Fault> </s:Body> </s:Envelope> 

Here's the binding:

 <bindings> <basicHttpBinding> <binding name="TransportBind" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> <security mode="Transport"> <transport clientCredentialType="None" /> </security> </binding> <binding name="basic" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> </binding> </basicHttpBinding> </bindings> 
+7
source share
3 answers

Your basicHttpBinding binding. You need to use wsHttpBinding .

+2
source

+1 @JohnSaunders because he most likely barks on the right tree here.

Is your client .NET / WCF? If not, it may not implement WS-Security, or at least not in the way WCF wants.

If the client is .NET, it is simply an inappropriate obligation on the client side.

The mustUnderstand flag indicates that the WS-Security header should be acknowledged and processed. The non-WS-Security client, regardless of whether it talks about WS-Security or is not configured, ignores the header, tries to use the message anyway, and the server will be punt.

Another option is to refuse a server failure. It will stop sending WS-Security headers. Of course, then you will not receive a refusal.

0
source

I solved this problem by not using the generated WS-Security header (when you add the service link) in the WCF configuration, but rather commenting on it and instead letting .NET generate the header using Client Credentials and specifying the Security mode "TransportWithMessageCredential":

 client.ClientCredentials.UserName.UserName = "UserName"; client.ClientCredentials.UserName.Password = "Password"; <basicHttpBinding> <binding name="Binding"> <security mode="TransportWithMessageCredential"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> 

(We use SSL, therefore, therefore, this security setting).

The generated title with comments:

  <client> <endpoint ...> <!--<headers> <wsse:Security...> </wsse:Security> </headers>--> </endpoint> </client> 

Unfortunately, I don’t know enough WCF to capture an unhandled soap request / response to compare the difference and understand why ClientCredentials does not cause a “did not understand” error, while the generated header does.

As an aside, according to the MSDN documentation , if you use only "Transport", he will not know how to use WS-Security: "Leave this property by default, that is, System.ServiceModel.SecurityMode.Transport, so as not to use WS -Security ".

0
source

All Articles