Overriding the Identity of a Service for Authentication

Typically, you do not have to set the identity on a service because the selection of a client credential type dictates the type of identity exposed in the service metadata. For example, the following configuration code uses the <wsHttpBinding> element and sets the clientCredentialType attribute to Windows.

<configuration>
<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_Windows">
        <security mode="Message">
          <message clientCredentialType="Windows"
                   establishSecurityContext="false"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <!-- other configuration code not shown -->
</system.serviceModel>
</configuration>

The following Web Services Description Language (WSDL) fragment shows the identity for the endpoint previously defined. In this example, the service is running as a self-hosted service under a particular user account (username@contoso.com) and therefore the user principal name (UPN) identity contains the account name. The UPN is also known as the user logon name in a Windows domain.

<wsdl:service name="CalculatorService">
  <wsdl:port name="WSHttpBinding_ICalculator_Windows"
    binding="tns:WSHttpBinding_ICalculator_Windows">
    <soap12:address 
      location=
      "https://localhost:8003/servicemodelsamples/service/upnidentity" />
    <wsa10:EndpointReference>
      <wsa10:Address>
        https://localhost:8003/servicemodelsamples/service/upnidentity
      </wsa10:Address>
      <Identity  
        xmlns="https://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
        <Upn>username@contoso.com</Upn>
      </Identity>
    </wsa10:EndpointReference>
  </wsdl:port>
</wsdl:service>

For a sample application that demonstrates identity setting, see Service Identity Sample. For more information about service identity, see Service Identity and Authentication.

Kerberos Authentication and Identity

By default, when a service is configured to use a Windows credential, an <identity> element that contains a <userPrincipalName> or <servicePrincipalName> element is generated in the WSDL. If the service is running under the LocalSystem, LocalService, or NetworkService account, a service principal name (SPN) is generated by default in the form of host/<hostname> because those accounts have access to the computer's SPN data. If the service is running under a different account, Windows Communication Foundation (WCF) generates a UPN in the form of <username>@<domainName>. This occurs because Kerberos authentication requires that a UPN or SPN be supplied to the client to authenticate the service.

You can also use the Setspn.exe tool to register an additional SPN with a service's account in a domain. You can then use the SPN as the identity of the service. To download the tool, see Windows 2000 Resource Kit Tool : Setspn.exe. For more information about the tool, see Setspn Overview.

Note

To use the Windows credential type without negotiation, the service's user account must have access to the SPN that is registered with the Active Directory domain. You can do this in the following ways:

  • Use the NetworkService or LocalSystem account to run your service. Because those accounts have access to the machine SPN that is established when the machine joins the Active Directory domain, WCF automatically generates the proper SPN element inside the service's endpoint in the service's metadata (WSDL).

  • Use an arbitrary Active Directory domain account to run your service. In this case, establish an SPN for that domain account, which you can do by using the Setspn.exe utility tool. Once you create the SPN for the service's account, configure WCF to publish that SPN to the service's clients through its metadata (WSDL). This is done by setting the endpoint identity for the exposed endpoint, either through an application configuration file or code.

For more information about SPNs, the Kerberos protocol, and Active Directory, see Kerberos Technical Supplement for Windows.

When SPN or UPN Equals the Empty String

If you set the SPN or UPN equal to an empty string, a number of different things happen, depending on the security level and authentication mode being used:

  • If you are using transport level security, NT LanMan (NTLM) authentication is chosen.

  • If you are using message level security, authentication may fail, depending on the authentication mode:

  • If you are using spnego mode and the AllowNtlm attribute is set to false, authentication fail.

  • If you are using spnego mode and the AllowNtlm attribute is set to true, authentication fails if the UPN is empty, but succeeds if the SPN is empty.

  • If you are using Kerberos direct (also known as "one-shot"), authentication fails.

Using the <identity> Element in Configuration

If you change the client credential type in the binding previously shown to Certificate**,** then the generated WSDL contains a Base64 serialized X.509 certificate for the identity value as shown in the following code. This is the default for all client credential types other than Windows.

<Identity xmlns="https://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
 <X509Data>
 <X509Certificate>MIIBxjCCAXSgAwIBAgIQmXJgyu9tro1M98GifjtuoDAJBgUrDgMCHQUAMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5MB4XDTA2MDUxNzIxNDQyNVoXDTM5MTIzMTIzNTk1OVowKTEQMA4GA1UEChMHQ29udG9zbzEVMBMGA1UEAxMMaWRlbnRpdHkuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBmivcb8hYbh11hqVoDuB7zmJ2y230f/b4e+4P6yXtKKuhUdYcIqc8mAforIM4WWJEVGeJVq9sFEwqrL5Ryid8jMTRwPLvA/x/wvj1gtD1GWJ+aUh2pqieiGL7MWTepHAQBIibUxgOrAOz0j9Xhg0iDFYScdYUjeqI3yZIDC7WbwIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBADB/J2QjdSPL8Doj3pAveCXd/5fY03eo9kUym/Tmb4ubdqsObri0qnYR/n8Wxsa1yJ4Dks6cNBTPS4l5B7zUeNo=</X509Certificate> 
 </X509Data>
</KeyInfo>
</Identity>

You can change the value of the default service identity or change the type of the identity by using the <identity> element in configuration or by setting the identity in code. The following configuration code sets a domain name system (DNS) identity with the value contoso.com.

Setting Identity Programmatically

Your service does not have to explicitly specify an identity, because WCF automatically determines it. However, WCF allows you to specify an identity on an endpoint, if required. The following code adds a new service endpoint with a specific DNS identity.

Dim ep As ServiceEndpoint = myServiceHost.AddServiceEndpoint(GetType(ICalculator), New WSHttpBinding(), String.Empty)
Dim myEndpointAdd As New EndpointAddress(New Uri("https://localhost:8088/calc"), EndpointIdentity.CreateDnsIdentity("contoso.com"))
ep.Address = myEndpointAdd
ServiceEndpoint ep = myServiceHost.AddServiceEndpoint(
                typeof(ICalculator),
                new WSHttpBinding(),
                String.Empty);
EndpointAddress myEndpointAdd = new EndpointAddress(new Uri("https://localhost:8088/calc"),
     EndpointIdentity.CreateDnsIdentity("contoso.com"));
ep.Address = myEndpointAdd;

See Also

Tasks

How to: Create a Custom Client Identity Verifier

Concepts

Service Identity and Authentication