Sometimes when you "add service reference" in VS 2008 you will get a few warnings (see below). When using svcutil like this:
these warnings may appear as errors.
If you get these errors/warnings:
Then (usually) you have nothing to worry about. What they mean is that your WSDL contains a binding which uses HTTP Post transport. For example:
WCF does not support this binding and so raised an error. So why you have nothing to worry about? The reason is that usually when a WSDL contains a HTTP Post binding it also contains a SOAP one and WCF can work with it. For example:
Actually you can see that even though errors have occured a functioning proxy was still generated.
Note that if you create a .NET 2.0 (asmx) web service then there is a configuration to determine if a HTTP Post binding should be created. I can't find it now but promise to post the details later on...
This time I will talk about the importance of order within xml elements.
Let's say we have a web service with this schema:
So of course this is a valid request:
But about about this?
This is not a valid xml instance!
The reason is that the schema contains the element which requires its sub elements to have order.
So why is it an interoperability gotcha?
The reason is that different soap stacks by different vendors behave differently in such cases. Sometimes even different stacks of the same vendor are divided...
Let's see how a .Net 2.0 proxy would look like:
This proxy can parse both xml instances from above.
This is how the equivalent WCF proxy would look like:
This proxy is stricter and actually enforces the order of elements. So it would only accept the first (legal) instance and will give unexpected results with the second. It would usually not throw an exception but rather ignore the message and use default values for the unordered elements so your fields will have a lot of NULL's and zeros.
How to fix it?
Option 1 (recommended) - Send XML with the correct order.
Option 2 - Change the WSDL to use <all> instead of <sequence>. The former does not require correct order of elements (there are some other subtle differences). Note that in case the WSDL is dynamically generated this may be hard to maintain.
Option 3 - Remove the "Order=..." property from the WCF proxy. Note that when the proxy will be regenerated the "Order" property will come back so this is also a maintenance challenge.
When a custom binding is used in WCF it is possible to configure the value of requireSecurityContextCancellation. The name of this property doesn't exactly indicate in what scenarios it should be used.
When the client and server use WS-SecureConversation (by setting authenticationMode to "SecureConversation") the client get some token from the server in the initial handshake and needs to send it in every connection attempt. The server can extract this token and find the relevant data of this session in its memory. But what happens when the server/IIS is restarted? The memory is cleared and the session becomes invalid. The way to overcome this is to set requireSecurityContextCancellation to false (the default is true). In this mode the session key is saved at the client side and it sends it to the server in every request. This means that even if the server is restarted the session key is available in the request. This also means that the size of each request is a little bigger.
Since with this mode the server does not need to save the session key it does not need to be informed when the session is over and from here the property name requireSecurityContextCancellation.
Richard Blewett has published a great post about WCF sessions. He explains how sessions are implemented in each of the bindings and how they can be used.
One addition over this post is that sessions can also be used in WCF via the asp.net compatibility mode. Here, the way to access the session is:
In this mode the session is implemented via an HTTP cookie - exactly as with classic .Net 2.0 web services / asp.net. This means that this mode is available only when hosting in IIS and using HTTP transport. This mode should be used in case backward compatibility with an old service/client is required. It should not be used with new services as it adds some overhead to the pipeline.
Recently I had an interesting case with WCF "raw message" contract:
The message I used on the client side contained some SOAP headers. Since this is an untyped message these headers were neither encrypted nor signed. That was a show stopper for me.
However the request message was still not being encrypted nor signed. I struggled with this issue for some time until I was lucky enough to find Pedro Felix's message in the WCF MSDN forum:
In other words the OutgoingSignatureParts always relates to server outgoing messages while client outgoing stuff is always considered as "incoming". After fixing this the code worked like a charm. I probably should have proactively RTFM myself but at least I felt good for not being the only one who fell for this...
First attempt - using basicHttpBinding with MessageClientCredentialType of "Username". Unfortunetelly this would yield the following exception:
Second attempt - using basicHttpBinding with TransportWithMessageCredential mode.
Since this mode implies that we need to secure the transport we get any of these exceptions, depending if we are on the client or the server side:
Third attempt - using wsHttpBinding with MessageClientCredentialType of "Username".
Depending on several other settings, and wheather we're on the client or the server, we would get any of these exceptions:
Forth attempt - using wsHttpBinding with TransportWithMessageCredential mode.
Similarily to the second attempt we get:
OR
Fifth attempt - using customBinding with httpTransport and security element with authenticationMode of UserNameOverTransport
This time we get:
So it really seems like Microsoft is trying to (im)politely convince us not to use clear username/password. But what can we do for cases where this behaviour is really required?
The solution
The solution s to use ClearUsernameBinding. This binding seamlessly integrates with WCF and allows us to use clear username/password.
Many web services authenticate clients using username/password. In the soap message it looks like this:
You can notice that the username/password are clear (not encrypted). This means that everyone that can see this message can steal the password.
There are typically 3 ways to overcome this.
1. Sending the hashed password only:
Where the digest is calculated from the password, a timestamp and a nonce. However this is not really secure. A hacker can use a dictionary attack to extract the password.
2. Protecting the username with SSL. This is a valid option but is limited to HTTP web service only and denies us from some of the rich WS-Security options. There are some other transports which are inherently secured (like SSL passthrough of load balancers as F5's BIG-IP) but I will not discuss them here.
3. Protecting the username with message-level X.509 certificate. This is another valid option but sometimes more complex to implement.
In practice if you want to use username/password you would need to decide between options 2&3. Some frameworks, like Microsoft's WCF, even prevents you from using option #1 at all. Nevertheless there are a few exceptions where option #1 is valid:
Your network is inherently secured so you are not afraid of password stealers.
You are required to interoperate with a service that requires to send clear username/password