In Windows Communication Foundation (WCF), the service dictates the security requirements for clients. That is, the service specifies what security mode to use, and whether or not the client must provide a credential. The process of securing a client, therefore, is simple: use the metadata obtained from the service (if it is published) and build a client. The metadata specifies how to configure the client. If the service requires that the client supply a credential, then you must obtain a credential that fits the requirement. This topic discusses the process in further detail. For more information about creating a secure service, see Securing Services.
The Service Specifies Security
By default, WCF bindings have security features enabled. (The exception is the BasicHttpBinding.) Therefore, if the service was created using WCF, there is a greater chance that it will implement security to ensure authentication, confidentiality, and integrity. In that case, the metadata the service provides will indicate what it requires to establish a secure communication channel. If the service metadata does not include any security requirements, there is no way to impose a security scheme, such as Secure Sockets Layer (SSL) over HTTP, on a service. If, however, the service requires the client to supply a credential, then the client developer, deployer, or administrator must supply the actual credential that the client will use to authenticate itself to the service.
When creating a client, the first step is to obtain the metadata for the service that the client will communicate with. This can be done in two ways. First, if the service publishes a metadata exchange (MEX) endpoint or makes its metadata available over HTTP or HTTPS, you can download the metadata using the ServiceModel Metadata Utility Tool (Svcutil.exe), which generates both code files for a client as well as a configuration file. (For more information about using the tool, see Accessing Services Using a WCF Client.) If the service does not publish a MEX endpoint and also does not make its metadata available over HTTP or HTTPS, you must contact the service creator for documentation that describes the security requirements and the metadata.
|It is recommended that the metadata come from a trusted source and that it not be tampered with. Metadata retrieved using the HTTP protocol is sent in clear text and can be tampered with. If the service uses the HttpsGetEnabled and HttpsGetUrl properties, use the URL the service creator supplied to download the data using the HTTPS protocol.|
Metadata sources can be divided into two broad categories: trust sources and untrusted sources. If you trust a source and have downloaded the client code and other metadata from that source's secure MEX endpoint, then you can build the client, supply it with the right credentials, and run it with no other concerns.
However, if you elect to download a client and metadata from a source that you know little about, be sure to validate the security measures the code uses. For example, you must not simply create a client that sends your personal or financial information to a service unless the service demands confidentiality and integrity (at the very least). You should trust the owner of the service to the extent that you are willing to disclose such information because such information will be visible to him or her.
As a rule, therefore, when using code and metadata from an untrusted source, check the code and metadata to ensure that it meets the security level that you require.
Setting a Client Credential
Setting a client credential on a client consists of two steps:
Determine the client credential type the service requires. This is accomplished by one of two methods. First, if you have documentation from the service creator, it should specify the client credential type (if any) the service requires. Second, if you have only a configuration file generated by the Svcutil.exe tool, you can examine the individual bindings to determine what credential type is required.
Specify an actual client credential. The actual client credential is called a client credential value to distinguish it from the type. For example, if the client credential type specifies a certificate, you must supply an X.509 certificate that is issued by a certificate authority the service trusts.
Determining the Client Credential Type
If you have the configuration file the Svcutil.exe tool generated, examine the <bindings> section to determine what client credential type is required. Within the section are binding elements that specify the security requirements. Specifically, examine the <security> Element of each binding. That element includes the mode attribute, which you can set to one of three possible values (Message, Transport, or TransportWithMessageCredential). The value of the attribute determines the mode, and the mode determines which of the child elements is significant.
<security> element can contain either a
<message> element, or both. The significant element is the one that matches the security mode. For example, the following code specifies that the security mode is
"Message", and the client credential type for the
<message> element is
"Certificate". In this case, the
<transport> element can be ignored. However, the
<message> element specifies that an X.509 certificate must be supplied.
<wsHttpBinding> <binding name="WSHttpBinding_ICalculator"> <security mode="Message"> <transport clientCredentialType="Windows" realm="" /> <message clientCredentialType="Certificate" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" /> </security> </binding> </wsHttpBinding>
Note that if the
clientCredentialType attribute is set to
"Windows", as shown in the following example, you do not need to supply an actual credential value. This is because the Windows integrated security provides the actual credential (a Kerberos token) of the person who is running the client.
<security mode="Message"> <transport clientCredentialType="Windows " realm="" /> </security>
Setting the Client Credential Value
If it is determined that the client must supply a credential, use the appropriate method to configure the client. For example, to set a client certificate, use the SetCertificate method.
A common form of credential is the X.509 certificate. You can supply the credential in two ways:
By programming it in your client code (using the SetCertificate method).
By adding a <behaviors> section of the configuration file for the client and using the
clientCredentials element (shown below).
Setting a <clientCredentials> Value in Code
To set a <clientCredentials> value in code, you must access the ClientCredentials property of the ClientBase class. The property returns a ClientCredentials object that allows access to various credential types, as shown in the following table.
Returns an X509CertificateInitiatorClientCredential
Represents an X.509 certificate provided by the client to authenticate itself to the service.
Returns an HttpDigestClientCredential
Represents an HTTP digest credential. The credential is a hash of the user name and password.
Returns an IssuedTokenClientCredential
Represents a custom security token issued by a Security Token Service, commonly used in federation scenarios.
Returns a PeerCredential
Represents a Peer credential for participation in a Peer mesh on a Windows domain.
Returns an X509CertificateRecipientClientCredential
Represents an X.509 certificate provided by the service in an out-of-band negotiation.
Returns a UserNamePasswordClientCredential
Represents a user name and password pair.
Returns a WindowsClientCredential
Represents a Windows client credential (a Kerberos credential). The properties of the class are read-only.
Setting a <clientCredentials> Value in Configuration
Credential values are specified by using an endpoint behavior as child elements of the <clientCredentials> element. The element used depends on the client credential type. For example, the following example shows the configuration to set an X.509 certificate using the <clientCertificate> of <clientCredentials> Element.
<configuration> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="myEndpointBehavior"> <clientCredentials> <clientCertificate findvalue="myMachineName" storeLocation="Current" X509FindType="FindBySubjectName" /> </clientCredentials> </behavior> </behaviors> </system.serviceModel> </configuration>
To set the client credential in configuration, add an <endpointBehaviors> element to the configuration file. Additionally, the added behavior element must be linked to the service's endpoint using the
behaviorConfiguration attribute of the <endpoint> element as shown in the following example. The value of the
behaviorConfiguration attribute must match the value of the behavior name attribute.
|Some of the client credential values cannot be set using application configuration files, for example, user name and password, or Windows user and password values. Such credential values can be specified only in code.|
For more information about setting the client credential, see How to: Specify Client Credential Values.
<wsHttpBinding> <binding name="PingBinding"> <security mode="TransportWithMessageCredential" > <message clientCredentialType="UserName" establishSecurityContext="false" negotiateServiceCredential="false" /> <transport clientCredentialType="Certificate" /> </security> </binding> </wsHttpBinding>
TasksHow to: Specify Client Credential Values
How to: Specify the Client Credential Type
Accessing Services Using a WCF Client
Configuration Editor Tool (SvcConfigEditor.exe)
ServiceModel Metadata Utility Tool (Svcutil.exe)