For my current project, I'm involved in writing some intranet services using WCF. For some dogmatic reason, we are not allowed to use the traditional WCF bindings for intranet scenario's, like the NetTcpBinding or the NetNamedPipeBinding. The only downside for using these bindings is the fact that we cannot use IIS (at least until IIS 7.0) for hosting these services. I personally can live with this restriction as it is very easy to host a WCF service in a Windows Service until Windows Server 2008 becomes available (which should be very soon) which includes IIS 7.0/ WAS.
Anyway, as this roots out the right tool for the right job, we are stuck with using the HTTP bindings for out intranet services (the WsHttpBinding to be more accurate). Today, I encountered one of the consequences in doing this.
Out tester-on-duty performs his tests with a WinForms sample application that uses one of the intranet services. When the application starts, he makes two calls to the service. Then he leaves the application alone for a while. After an hour or so, he comes back and sends another request to the service. The following error message appears:
Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
After some reading on the web and some books on WCF, I solved the issue by tweaking the WsHttpBinding configuration like so:
<wsHttpBinding> <binding name="customWsHttpBinding"> <security mode="Message"> <message negotiateServiceCredential="false" establishSecurityContext="false"/> </security> </binding> </wsHttpBinding>
The negotiateServiceCredential setting determines whether negotiation takes place between the client and the service to determine a session key for signing and encryption. The establishSecurityContext setting reduces the overhead for repeatable communications between a client and a server by removing the re-authentication of credentials that are supplied by the client. Would I had this problem if I was using one of the bindings that are meant to be used for intranet scenario's? Probably not. The default settings for these bindings are optimized for this scenario. The default settings for the HTTP bindings are optimized for Internet scenario's.
Using an HTTP binding for intranet scenario's is certainly possible, but as it appears, it involves some pain and configuration hell to get it right. Just use the correct binding (if possible :-) ) for the scenario at hand. It will save you a lot of grief.
Update: It appears that I jumped to conclusions a bit too soon. The thing that was causing this problem was the fact that I was caching the service proxy as a side effect of putting the encapsulating tasks class in a service locator. This caused the timeouts for the security session. I feel stupid that I didn't notice this a bit sooner. My opinion on using the right binding for the scenario at hand still stands. I still believe that the NetTcpBinding or the NetNamedPipeBinding is more appropriate for the services I'm building.