10/29/10

WCF Secure Channel cannot be opened - Load Balancing with wsHttp Binding

When a WCF service generates the following error:
Exception:
Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint.

Inner Exception:
The request for security token has invalid or malformed elements.



This probably means that the service is running under a load balanced environment, and the WCF settings are not configured correctly. This error is intermittent because the load balancer may be landing on the same server, but when the request is sent to a different server the security token becomes invalid. When using the wsHttpBinding on a Load balanced environment , it is necessary to turn off the security context establishment. The establishSecurityContext attribute should be set to false. By default, this value is true. This needs to be added to both the host and client configurations.The host configuration should look something like this:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingLB">
     <security mode="Message">
         <message clientCredentialType="Windows" establishSecurityContext="false"/>
      </security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
    <behavior name="ozkary.SerBehavior">
    <serviceMetadata httpGetEnabled="true" />
    <serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ozkary.SerBehavior" name="ozkary.Service">
     <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBindingLB"             contract="ozkary.IService">                   
                </endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>   
</system.serviceModel>


The client configuration should look as follows:
<system.serviceModel>
<bindings>
<wsHttpBinding>
   <binding name="wsHttpBindingLB">               
    <security mode="Message">                    
         <message clientCredentialType="Windows"  establishSecurityContext="false"/>
    </security>
    </binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint  address="myService.svc" binding="wsHttpBinding"
        bindingConfiguration="wsHttpBindingLB" contract="ozkary.IService">               
</endpoint>
</client>  
</system.serviceModel>

Another approach to address this error is to add another endpoint and use BasicHttpBinding instead. This by default provides persistent connections, but if you do not want the persistent connection, it can be disabled by setting the KeepAliveEnabled attribute to false. To learn more about configuring WCF services in a load balanced environment, you can read the following from MSDN:
I hope this helps.