My WCF service was working when testing on my laptop. After deploying to a dev environment where the client/caller and server/WCF were on different machines, I got this error:
System.ServiceModel.Security.SecurityNegotiationException: A call to SSPI failed...System.ComponentModel.Win32Exception: The target principal name is incorrect
My situation is this:
Client (AD user) -> WCF Service (AD service account)
First, the solution. Two options:
- Instead of using the AD service account, use the Network Service account
- On the client, specify a dummy SPN
Why do these things work? Another
blog post explained the situation nicely.
For option #1, the Network Service account has access to the host machine SPN. Because of this, Kerberos authentication can be used. When the AD service account is used (like my scenario), it doesn't have access to the host machine SPN, so Kerberos fails and we get the SSPI exception.
For option #2, if a dummy SPN is used, Kerberos authentication will fail, however in this case authentication will fall back to NTLM and succeed.
An example client config section, using identity, is shown here:
<identity> <servicePrincipalName value="MySystem/Service1"/></identity>
It can also be done programmatically (second line):
var uri = new Uri(ConfigurationManager.AppSettings["serviceAddress"]);var endpointIdentity = EndpointIdentity.CreateSpnIdentity("");var endpointAddress = new EndpointAddress(uri, endpointIdentity);return _channelFactory.CreateChannel(endpointAddress);
If the client doesn't explicitly specify an identity, WCF will automatically create an identity using the host name in the Uri. If we are calling net.tcp://remotemachine1:port/MyService, the WCF client will use the machine name as the SPN, like this:
EndpointIdentity.CreateSpnIdentity("remotemachine1")
That's what will be used to call the service. When this happens, Kerberos authentication will fail, WCF will not fall back to NTLM, and we get the exception.