Wednesday, June 24, 2009

Service principal name when using WCF, net.tcp binding, and a domain service account

Service Principal Names (SPN) allow you to assign a name to a service and it will be used as a simple authentication mechanism. Basically, when the client connects to the service, the service sends the client it's SPN. The client also knows what SPN it expects. If they match, things are good.

In order to use the WCF NetTcpBinding with a Windows Service, it is necessary to create a SPN.

Here's the scenario:

We have a Windows Service that exposes a WCF NetTcpBinding service. The Windows service runs as a domain user account instead of LOCAL SYSTEM, NETWORK SERVICE, etc. Let's say the service is running under the account MyDomain\MyServiceAccount.

We have a client on the domain that will access the WCF service.

The problem arises when the client tries to talk to the server. Without an SPN, there is no way for the client to verify it has reached the appropriate service.

So, how do you use an SPN...

  1. We need to create an SPN and associate it with the service account. This is done using a utility called setspn.exe that is located in the Windows 2003 Support Tools.
  2. We need to create the SPN. An SPN consists of two parts, service and host. The format is \. In our case, the host really doesn't matter because we will attach the SPN to a username, not a computer. Here's the command:
    setspn -A MyServiceClass\MyHostName MyDomain\MyServiceAccount
  3. Next, on the client, we need to specify the SPN when we create an endpoint mapping. This can be done using the app.config file or programmatically. In the app.config file, in the section, add

       <serviceprincipalname value="MyServiceClass\MyHostName"/>

    Or we create the endpoint with the SPN..

    EndpointIdentity id = EndpointIdentity.CreateSpnIdentity("MyServiceClass\MyHostName");
    EndpointAddress addr = new EndpointAddress(new Uri(URI), id);

That's it. Now your client will be able to verify the service it is connecting to.