By using of the x509 certificate authentication with message security there are many things, which can go wrong. In such cases the problem diagnostic could be very confusing and time intensive. For this reason I used some of calculator examples from the SDK and described this configuring process step by step.
The full example can be downloaded here.
1. Create the Service and Client without any security.
2. Create the service certificate:
Following example shows how to create the self-signed certificate with the subject name www.testsvc.eu at the machine hosting the service:
makecert.exe -sr LocalMachine -ss My -n CN=www.testsvc.eu -sky exchange -sk –pe
After the certificate is created it can be found in the MMC LocalMachine Personal Store.
3. Create the client certificate:
Next example shows how to create the self-signed certificate for the client at the client machine. The used subject name is www.testclient.eu:
makecert.exe -sr CurrentUser -ss My -n CN=www.testclient.eu -sky exchange -sk -pe
After the certificate is created it can be found in the MMC CurrentUser Personal Store.
4. After both certificates are created, copy the certificate www.testclient.eu from CurrentUser Personal Store (from the client machine) to the CurrentUser Trusted People store (to the client machine) and to the LocalMachine Trusted People Store of the machine hosting the service.
5. Similar to 4, copy the certificate www.testsvc.eu from the LocalMachine Personal store (from the service machine) to the CurrentUser Trusted People store of the machine running the client.
6. Configure the service as shown in the next example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="www.testsvc.eu" />
</identity>
</endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode ="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceCredentials>
<serviceCertificate findValue="www.testsvc.eu" 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 will be 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 to have 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>
</system.serviceModel>
</configuration>
7. Configure the client as shown in the following example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8000/daenetsamples/testservice.eu"
behaviorConfiguration="ClientCertificateBehavior" binding="wsHttpBinding"
bindingConfiguration="Binding1" contract="Microsoft.ServiceModel.Samples.ICalculator"
name="">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine"
x509FindType="FindBySubjectName" findValue="www.testsvc.eu" />
</identity>
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message" >
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<!--
The clientCredentials behavior allows one 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="www.testclient.eu" 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 will be 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 to have 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>
</configuration>
At the I posted some exceptions, which are mostly thrown if something goes wrong.
If no endpoint identity has been specified and certificate CN different than ‘localhost’
An unhandled exception of type 'System.ServiceModel.Security.MessageSecurityException' occurred in mscorlib.dll
Additional information: Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'localhost' but the remote endpoint provided DNS claim 'www.testsvc.eu'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'www.testsvc.eu' as the Identity property of EndpointAddress when creating channel proxy.
If the server’s certificate can not be found in the Trusted People store of the client’s machine.
An unhandled exception of type 'System.ServiceModel.Security.SecurityNegotiationException' occurred in mscorlib.dll
Additional information: SOAP security negotiation with 'http://localhost:8000/daenetsamples/testservice.eu' for target 'http://localhost:8000/daenetsamples/testservice.eu' failed. See inner exception for more details.
If the client’s certificate can not in the CurrentUser’s trusted People store of the machine which hosts the service:
An unhandled exception of type 'System.ServiceModel.Security.SecurityNegotiationException' occurred in mscorlib.dll
Additional information: The caller was not authenticated by the service.
Posted
Sep 24 2006, 11:52 PM
by
Damir Dobric