Message Security Certificate
This sample demonstrates how to implement an application that uses WS-Security with X.509 v3 certificate authentication for the client and requires server authentication using the server's X.509 v3 certificate. This sample uses default settings such that all application messages between the client and server are signed and encrypted. This sample is based on the WSHttpBinding and consists of a client console program and a service library hosted by Internet Information Services (IIS). The service implements a contract that defines a request-reply communication pattern.
Note
The setup procedure and build instructions for this sample are located at the end of this topic.
The sample demonstrates controlling authentication using configuration and how to obtain the caller’s identity from the security context, as shown in the following sample code.
public class CalculatorService : ICalculator
{
public string GetCallerIdentity()
{
// The client certificate is not mapped to a Windows identity by default.
// ServiceSecurityContext.PrimaryIdentity is populated based on the information
// in the certificate that the client used to authenticate itself to the service.
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
...
}
The service exposes one endpoint for communicating with the service and one endpoint for exposing the service's WSDL document using WS-MetadataExchange protocol, defined using the configuration file (Web.config). The endpoint consists of an address, a binding, and a contract. The binding is configured with a standard wsHttpBinding element, which defaults to using message security. This sample sets the clientCredentialType attribute to Certificate to require client authentication.
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- Use the base address provided by host. -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<!-- The mex endpoint is exposed at https://localhost/servicemodelsamples/service.svc/mex. -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding name="Binding1">
<security mode ="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
The behavior specifies the service's credentials that are used when the client authenticates the service. The server certificate subject name is specified in the findValue attribute in the serviceCredentials element.
<!--For debugging purposes, set the includeExceptionDetailInFaults attribute to true.-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows you to define a service certificate.
A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
This configuration references the "localhost" certificate installed during the set up instructions.
-->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<clientCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it is trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having certificates issued by a certificate authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
The client endpoint configuration consists of an absolute address for the service endpoint, the binding, and the contract. The client binding is configured with the appropriate security mode and authentication mode. When running in a cross-machine scenario, ensure that the service endpoint address is changed accordingly.
<system.serviceModel>
<client>
<!-- Use a behavior to configure the client certificate to present to the service. -->
<endpoint address="https://localhost/servicemodelsamples/service.svc"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</client>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding name="Binding1">
<security mode ="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
...
</system.serviceModel>
The client implementation can set the certificate to use, either through the configuration file or through code. The following sample shows how to set the certificate to use in the configuration file.
<system.serviceModel>
...
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<!--
The clientCredentials behavior allows you to define a certificate to present to a service.
A certificate is used by a client to authenticate itself to the service and provide message integrity.
This configuration references the "client.com" certificate installed during the setup instructions.
-->
<clientCredentials>
<clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
<serviceCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it is trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having certificates issued by a certificate authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
The following sample shows how to call the service in your program.
// Create a client.
CalculatorClient client = new CalculatorClient();
// Call the GetCallerIdentity service operation.
Console.WriteLine(client.GetCallerIdentity());
...
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();
When you run the sample, the operation requests and responses are displayed in the client console window. Press ENTER in the client window to shut down the client.
CN=client.com
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.
The Setup.bat batch file included with the Message Security samples enables you to configure the client and server with relevant certificates to run a hosted application that requires certificate-based security. The batch file can be run in three modes. To run in single-machine mode type setup.bat at the command line; for service mode type setup.bat service; and for client mode type setup.bat client. Use the client and server mode when running the sample across machines. See the set up procedure at the end of this topic for details. The following provides a brief overview of the different sections of the batch files so that they can be modified to run in appropriate configuration:
Creating the client certificate.
The following line in the batch file creates the client certificate. The client name specified is used in the subject name of the certificate created. The certificate is stored in
My
store at theCurrentUser
store location.echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
Installing the client certificate into server’s trusted certificate store.
The following line in the batch file copies the client certificate into the server's TrustedPeople store so that the server can make the relevant trust or no-trust decisions. In order for a certificate installed in the TrustedPeople store to be trusted by a Windows Communication Foundation (WCF) service, the client certificate validation mode must be set to
PeerOrChainTrust
orPeerTrust
value. See the previous service configuration sample to learn how this can be done using a configuration file.echo ************ echo copying client cert to server's LocalMachine store echo ************ certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
Creating the server certificate.
The following lines from the Setup.bat batch file create the server certificate to be used.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
The %SERVER_NAME% variable specifies the server name. The certificate is stored in the LocalMachine store. If the Setup.bat batch file is run with an argument of service (such as, setup.bat service
) the %SERVER_NAME% contain
sthe fully-qualified domain name of the computer. Otherwise it defaul
tsto localhost.
Installing server certificate into the client’s trusted certificate store.
The following line copies the server certificate into the client trusted people store. This step is required because certificates generated by Makecert.exe are not implicitly trusted by the client system. If you already have a certificate that is rooted in a client trusted root certificate—for example, a Microsoft-issued certificate—this step of populating the client certificate store with the server certificate is not required.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Granting permissions on the certificate's private key.
The following lines in the Setup.bat file make the server certificate stored in the LocalMachine store accessible to the ASP.NET worker process account.
echo ************ echo setting privileges on server certificates echo ************ for /F "delims=" %%i in ('"%ProgramFiles%\ServiceModelSampleTools\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R iisreset
Note
If you are using a non-U.S. English edition of Microsoft Windows you must edit the Setup.bat file and replace the "NT AUTHORITY\NETWORK SERVICE" account name with your regional equivalent.
Note
The tools used in this batch file are located in either C:\Program Files\Microsoft Visual Studio 8\Common7\tools or C:\Program Files\Microsoft SDKs\Windows\v6.0\bin. One of these directories must be in your system path. If you have Visual Studio installed, the easiest way to get this directory in your path is to open up the Visual Studio Command Prompt. Go to the start button, Select All Programs, Visual Studio 2005, Tools. This command prompt has the appropriate paths already configured. Otherwise you must to add the appropriate directory to your path manually.
To set up, build, and run the sample
Ensure that you have performed the One-Time Set Up Procedure for the Windows Communication Foundation Samples.
To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.
To run the sample on the same machine
Ensure that the path includes the folder where Makecert.exe and FindPrivateKey.exe are located.
Run Setup.bat from the sample install folder. This installs all the certificates required for running the sample.
Note
The Setup.bat batch file is designed to be run from a Windows SDK Command Prompt. It requires that the MSSDK environment variable point to the directory where the SDK is installed. This environment variable is automatically set within a Windows SDK Command Prompt.
Verify access to the service using a browser by entering the address https://localhost/servicemodelsamples/service.svc.
Launch Client.exe from \client\bin. Client activity is displayed on the client console application.
If the client and service are not able to communicate, see Troubleshooting Tips for WCF Samples.
To run the sample across machines
Create a directory on the service machine. Create a virtual application named servicemodelsamples for this directory using the Internet Information Services (IIS) management tool.
Copy the service program files from \inetpub\wwwroot\servicemodelsamples to the virtual directory on the service machine. Ensure that you copy the files in the \bin subdirectory. Also copy the Setup.bat, Cleanup.bat, and ImportClientCert.bat files to the service machine.
Create a directory on the client machine for the client binaries.
Copy the client program files to the client directory on the client machine. Also copy the Setup.bat, Cleanup.bat, and ImportServiceCert.bat files to the client.
On the server, run setup.bat service. Running setup.bat with the service argument creates a service certificate with the fully-qualified domain name of the machine and exports the service certificate to a file named Service.cer.
Edit Web.config to reflect the new certificate name (in the findValue attribute in the serviceCertificate element of serviceCredentials) which is the same as the fully-qualified domain name of the machine.
Copy the Service.cer file from the service directory to the client directory on the client machine.
On the client, run setup.bat client. Running setup.bat with the client argument creates a client certificate named client.com and exports the client certificate to a file named Client.cer.
In the Client.exe.config file on the client machine, change the address value of the endpoint to match the new address of your service. Do this by replacing localhost with the fully-qualified domain name of the server.
Copy the Client.cer file from the client directory to the service directory on the server.
On the client, run ImportServiceCert.bat. This imports the service certificate from the Service.cer file into the CurrentUser - TrustedPeople store.
On the server, run ImportClientCert.bat, This imports the client certificate from the Client.cer file into the LocalMachine - TrustedPeople store.
On the client machine, launch Client.exe from a command prompt window. If the client and service are not able to communicate, see Troubleshooting Tips for WCF Samples.
To clean up after the sample
Run Cleanup.bat in the samples folder once you have finished running the sample.
Note
This script does not remove service certificates on a client when running this sample across machines. If you have run Windows Communication Foundation (WCF) samples that use certificates across machines, be sure to clear the service certificates that have been installed in the CurrentUser - TrustedPeople store. To do this, use the following command:
certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
For example:certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
.
© 2007 Microsoft Corporation. All rights reserved.