How to: Specify Client Credential Values

Using Windows Communication Foundation (WCF), you can specify how a client is authenticated to the service. For example, you can stipulate that the client be authenticated to the service with a certificate. This example sets the security mode to Transport and sets the client credential type to Certificate.

The process occurs in three parts:

  1. The service developer specifies the credential type the client must supply.

  2. The client developer uses the ServiceModel Metadata Utility Tool (Svcutil.exe) to query the service for its metadata (service client code and configuration file).

  3. The client developer creates the client application and supplies a credential value, in either code or configuration, which matches the credential type, as stipulated in the metadata.

Service Code

To specify the client credential type on the service in code

  1. Add the following references to your code.

    Imports System
    Imports System.ServiceModel
    Imports System.ServiceModel.Security
    Imports System.Security.Cryptography.X509Certificates
    
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Security;
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceModel.Description;
    
  2. Create an instance of a binding. This example uses NetTcpBinding.

  3. Set the security mode, as appropriate. This example sets the mode to Transport.

  4. Set the ClientCredentialType to a credential, as appropriate. This example sets the type to a certificate.

  5. Create an instance of the ServiceHost using your service type in the constructor. For simplicity, the code to show the service interface and its implementation is not shown here.

  6. Set the credential value for the service. This example uses the SetCertificate method of the X509CertificateRecipientServiceCredential class.

    ' This string uses a function to prepend the computer name at run time.
    Dim addressTCP As String = String.Format("net.tcp://{0}:8036/Calculator", _
    System.Net.Dns.GetHostEntry("").HostName)
    
    Dim b As New NetTcpBinding()
    b.Security.Mode = SecurityMode.Transport
    b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate
    
    ' You must create an array of URI objects to have a base address.
    Dim a As New Uri(addressTCP)
    Dim baseAddresses() As Uri = {a}
    
    ' Create the ServiceHost. The service type (Calculator) is not
    ' shown here.
    Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)
    
    ' Add an endpoint to the service. Insert the thumbprint of an X.509 
    ' certificate found on your computer. 
    Dim c As Type = GetType(ICalculator)
    sh.AddServiceEndpoint(c, b, "MyCalculator")
    sh.Credentials.ServiceCertificate.SetCertificate( _
                    StoreLocation.LocalMachine, _
                    StoreName.My, _
                    X509FindType.FindBySubjectName, _
                    "contoso.com")
    
    ' This next line is optional. It specifies that the client's certificate
    ' does not have to be issued by a trusted authority, but can be issued
    ' by a peer if it is in the Trusted People store. Do not use this setting
    ' for production code. The default is PeerTrust, which specifies that 
    ' the certificate must originate from a trusted certifiate authority.
    ' sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
    ' X509CertificateValidationMode.PeerOrChainTrust
    Try
        sh.Open()
    
        Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
        Console.WriteLine("Listening @ {0}", address)
        Console.WriteLine("Press enter to close the service")
        Console.ReadLine()
        sh.Close()
    Catch ce As CommunicationException
        Console.WriteLine("A commmunication error occurred: {0}", ce.Message)
        Console.WriteLine()
    Catch exc As System.Exception
        Console.WriteLine("An unforseen error occurred: {0}", exc.Message)
        Console.ReadLine()
    End Try
    
    // This string uses a function to prepend the computer name at run time.
    string addressTCP = String.Format(
        "net.tcp://{0}:8036/Calculator",
        System.Net.Dns.GetHostEntry("").HostName);
    
    NetTcpBinding b = new NetTcpBinding();
    b.Security.Mode = SecurityMode.Transport;
    b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
    
    // You must create an array of URI objects to have a base address.
    Uri a = new Uri(addressTCP);
    Uri[] baseAddresses = new Uri[] { a };
    
    // Create the ServiceHost. The service type (Calculator) is not
    // shown here.
    ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);
    
    // Add an endpoint to the service. Insert the thumbprint of an X.509 
    // certificate found on your computer. 
    Type c = typeof(ICalculator);
    sh.AddServiceEndpoint(c, b, "MyCalculator");
    sh.Credentials.ServiceCertificate.SetCertificate(
        StoreLocation.LocalMachine,
        StoreName.My,
        X509FindType.FindBySubjectName,
        "contoso.com");
    
    // This next line is optional. It specifies that the client's certificate
    // does not have to be issued by a trusted authority, but can be issued
    // by a peer if it is in the Trusted People store. Do not use this setting
    // for production code. The default is PeerTrust, which specifies that 
    // the certificate must originate from a trusted certifiate authority.
    
    // sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
    // X509CertificateValidationMode.PeerOrChainTrust;
    try
    {
        sh.Open();
    
        string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
        Console.WriteLine("Listening @ {0}", address);
        Console.WriteLine("Press enter to close the service");
        Console.ReadLine();
        sh.Close();
    }
    catch (CommunicationException ce)
    {
        Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
        Console.WriteLine();
    }
    catch (System.Exception exc)
    {
        Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
        Console.ReadLine();
    }
    

To specify the client credential type on the service in configuration

  1. Add an appropriate binding to the <bindings> element. This example uses the <netTcpBinding Element>.

  2. Add a <security> of <netTcpBinding> to the binding. Be sure to set the required name attribute to an appropriate value.

  3. Set the mode attribute to an appropriate value. This example uses "Message" mode.

  4. Add either a transport or message element, as appropriate, to the security binding. This example uses the <message> element of <netTcpBinding>.

  5. Set the clientCredential attribute to the desired credential type. This example uses "Certificate".

    <bindings>
      <netTcpBinding>
        <binding name="TcpBindingWithCredential">
          <security mode="Message">
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    
  6. When creating the endpoint element, use the bindingConfiguration attribute value to specify the binding configuration, as shown in the following code.

    <endpoint address="myEndpointAddress"
              binding="netTcpBinding"
              bindingConfiguration="TcpBindingWithCredential"
                 name="netTcpBinding_ICalculator"
              contract="Microsoft.ServiceModel.Samples.ICalculator" />
    

Client Code

The following procedures demonstrate how to set the client credential value on the client in code and configuration. This assumes that you have used the ServiceModel Metadata Utility Tool (Svcutil.exe) to return the metadata (code and configuration) from the service. For more information, see How to: Create a Windows Communication Foundation Client.

To specify the client credential value on the client in code

  1. Use the ServiceModel Metadata Utility Tool (Svcutil.exe) to generate code and configuration from the service.

  2. Create an instance of the WCF client using the generated code.

  3. On the client class, set the ClientCredentials property of the ClientBase class to an appropriate value. This example sets the property to an X.509 certificate using the SetCertificate method of the X509CertificateInitiatorClientCredential class.

    ' Create a binding using Transport and a certificate.
    Dim b As New NetTcpBinding()
    b.Security.Mode = SecurityMode.Transport
    b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate
    
    ' Create an EndPointAddress.
    Dim ea As New EndpointAddress("net.tcp://localHost:8036/Calculator/MyCalculator")
    
    ' Create the client.
    Dim cc As New CalculatorClient(b, ea)
    
    ' Set the certificate for the client.
    cc.ClientCredentials.ClientCertificate.SetCertificate( _
    StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "cohowinery.com")
    Try
        cc.Open()
        ' Begin using the client.
        Console.WriteLine(cc.Divide(1001, 2))
        cc.Close()
    Catch adExc As AddressAccessDeniedException
        Console.WriteLine(adExc.Message)
        Console.ReadLine()
    Catch exc As System.Exception
        Console.WriteLine(exc.Message)
        Console.ReadLine()
    End Try
    
    // Create a binding using Transport and a certificate.
    NetTcpBinding b = new NetTcpBinding();
    b.Security.Mode = SecurityMode.Transport;
    b.Security.Transport.ClientCredentialType = 
        TcpClientCredentialType.Certificate;
    
    // Create an EndPointAddress.
    EndpointAddress ea = new EndpointAddress(
        "net.tcp://localHost:8036/Calculator/MyCalculator");
    
    // Create the client.
    CalculatorClient cc = new CalculatorClient(b, ea);
    
    // Set the certificate for the client.
    cc.ClientCredentials.ClientCertificate.SetCertificate(
        StoreLocation.LocalMachine,
        StoreName.My,
        X509FindType.FindBySubjectName,
        "cohowinery.com");
    try
    {
        cc.Open();
        // Begin using the client.
        Console.WriteLine(cc.Divide(1001, 2));
        cc.Close();
    }
    catch (AddressAccessDeniedException adExc)
    {
        Console.WriteLine(adExc.Message);
        Console.ReadLine();
    }
    catch (System.Exception exc)
    {
        Console.WriteLine(exc.Message);
        Console.ReadLine();
    }          
    

    You can use any of the enumerations of the X509FindType class. The subject name is used here in case the certificate is changed (due to an expiration date). Using the subject name enables the infrastructure to find the certificate again.

To specify the client credential value on the client in configuration

  1. Add a <behavior> of <endpointBehaviors> element to the <behaviors> element.

  2. Add a <serviceCredentials> element to the <behaviors> element. Be sure to set the required name attribute to an appropriate value.

  3. Add a <clientCertificate> of <serviceCredentials> element to the <clientCredentials> element.

  4. Set the following attributes to appropriate values: storeLocation, storeName, x509FindType, and findValue, as shown in the following code. For more information about certificates, see Working with Certificates.

    <behaviors>
       <endpointBehaviors>
          <behavior name="endpointCredential">
            <clientCredentials>
              <clientCertificate findValue="Contoso.com" 
                                 storeLocation="LocalMachine"
                                 storeName="TrustedPeople"
                                 x509FindType="FindBySubjectName" />
            </clientCredentials>
          </behavior>
       </endpointBehaviors>
    </behaviors>
    
  5. When configuring the client, specify the behavior by setting the behaviorConfiguration attribute of the <endpoint> element, as shown in the following code. The endpoint element is a child of the <client> element. Also specify the name of the binding configuration by setting the bindingConfiguration attribute to the binding for the client. If you are using a generated configuration file, the binding's name is automatically generated. In this example, the name is "tcpBindingWithCredential".

    <client>
      <endpoint name =""
                address="net.tcp://contoso.com:8036/aloha"
                binding="netTcpBinding"
                bindingConfiguration="tcpBindingWithCredential"
                behaviorConfiguration="credentialBehavior" />
    </client>
    

See Also

Tasks

How to: Create a Windows Communication Foundation Client

Reference

NetTcpBinding
SetCertificate
X509CertificateRecipientServiceCredential
ClientBase
X509CertificateInitiatorClientCredential

Concepts

Programming WCF Security
Selecting a Credential Type
Working with Certificates

Other Resources

ServiceModel Metadata Utility Tool (Svcutil.exe)
<netTcpBinding>
<security> of <netTcpBinding>
<message> element of <netTcpBinding>
<behavior> of <endpointBehaviors>
<behaviors>
<clientCertificate> of <serviceCredentials>
<clientCredentials>


© 2007 Microsoft Corporation. All rights reserved.
Last Published: 2010-03-21