WCF with certificates both on the client and on the server (message security and wsHttpBinding)

I am trying to configure a WCF service with certificate authentication on both the client and the server. I go through hell, looking through all the possible error messages.

The ultimate goal here is to authenticate both parties with certificates. I will issue a specific certificate for each client, which (I hope) will allow me to tell them separately.

So far I have the following configuration files:

Server configuration file

<configuration> <system.serviceModel> <services> <service name="ServiceApiImplementation" behaviorConfiguration="myBehaviour"> <host> <baseAddresses><add baseAddress="http://localhost:9110/MyService"/></baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="IServiceAPI" bindingName="SOAP12Binding"> <identity> <certificateReference findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/> </identity> </endpoint> </service> </services> <bindings> <wsHttpBinding> <binding name="SOAP12Binding" receiveTimeout="00:02:00" closeTimeout="00:01:00" openTimeout="00:01:00" sendTimeout="00:01:00"> <security mode="Message"> <message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" /> </security> </binding> </wsHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="myBehaviour"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <serviceCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" /> <clientCertificate> <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/> </clientCertificate> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration> 

Client configuration file

 <system.serviceModel> <client> <endpoint address="http://localhost:9110/MyService" binding="wsHttpBinding" bindingConfiguration="SOAP12Binding_IServiceAPI" contract="IServiceAPI" behaviorConfiguration="behaviour1" name="SOAP12Binding_IServiceAPI"> <identity> <!-- Value obtained when "Adding a Service Reference in visual studio" --> <certificate encodedValue="xxxxxxxxxxxxx" /> </identity> </endpoint> </client> <behaviors> <endpointBehaviors> <behavior name="behaviour1"> <clientCredentials> <clientCertificate findValue="ClientCertificate" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/> <serviceCertificate> <defaultCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" /> <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" /> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> <bindings> <wsHttpBinding> <binding name="SOAP12Binding_IServiceAPI"> <security mode="Message"> <message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" /> </security> </binding> </wsHttpBinding> </bindings> </system.serviceModel> 

I created rootCA and a couple of certificates for the client and server, given the appropriate permissions and put them in stores (both LocalMachine and CurrentUSer out of desperation). As far as I know, this bit works.

Problems arise when calling a service. Last error:

An unsecured or incorrectly protected error was received from another party. See Internal FaultException for error code and details.

The message could not be processed. This is most likely because the action "http://tempuri.org/IServiceAPI/MyMethod" is incorrect either because the message contains an invalid or expired security context token or because there is m ismatch between the bindings. The security context symbol will be invalid if the service interrupted the channel due to inactivity. To prevent interruption of unoccupied sessions, prematurely increases the reception timeout for binding to the service endpoint.

Or even (previous error)

Authentication failed for outgoing message. Expected Identity 'Identity (http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn )' for "Endpoint http: // localhost: 9110 / MyService".

Error messages depend on my experiments in the configuration files. Now the client and server are running on the same computer, so at least I expect each application to authenticate another through rootCA.

Please note that I use Message Security and wsHttpBinding because they looked right. I have no big restrictions other than publishing a service that can be used by standard JAVA platforms.

Can someone help me sort out this mess?

Any help would be greatly appreciated.

Hi,

+7
source share
2 answers

I managed to solve my original problem.

Regarding two-way certificate authentication, I found that the following code article provides a working demo: http: // www. codeproject.com/Articles/36683/9-simple-steps-to-enable-X-509-certificates-on-WCF#Step%201:-%20Create%20client%20and%20server%20certificates p>

Suppose this example uses peer-to-peer trust, but so far I have never been able to work with a working prototype, no matter what. From this point of view, the only errors that I look at keep the certificate chain in the right place and provide access to the private key to the user in whom your project is working. See this article for an explanation of how to grant permissions for a private key of a certificate: http://msdn.microsoft.com/en-us/library/ff647171.aspx#Step6

In the second part of the question: how to tell clients certificates separately in the WCF service ?, you can use the following code to get the fingerprint of the client certificate:

 X509Certificate2 certificate = null; if(ServiceSecurityContext.Current.AuthorizationContext.ClaimSets == null) throw new Exception("No claim set"); foreach(var claim in ServiceSecurityContext.Current.AuthorizationContext.ClaimSets) if(claim is X509CertificateClaimSet) { X509CertificateClaimSet xcset = claim as X509CertificateClaimSet; certificate = xcset.X509Certificate; break; } if(certificate == null) throw new Exception("No X509 certificate found"); string clientCertificateThumbprint = certificate.Thumbprint; 

This will cause the client fingerprint to be different for each client to whom you issue the certificate. Of course, all other certificate data is available.

+1
source

The message could not be processed. This is most likely due to the fact that the action "http://tempuri.org/IServiceAPI/MyMethod" is incorrect either because the message contains an invalid or expired security context token or because there is m ismatch between the bindings. The security context token would be invalid if the service terminated the channel due to inactivity. To prevent interruption of inactivity sessions, the service prematurely increases the reception timeout for binding to the service endpoint.

This means that the service request is turned off. Please refer to the Windows Event Viewer or enable logging in your service. See: http://msdn.microsoft.com/en-us/library/ms732023.aspx

Authentication failed for outgoing message. The expected identity is the identifier (http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn ) 'for the endpoint http: // localhost: 9110 / MyService.

This means that your indentity node is incorrectly pointing to the wrong place. Have you changed places of service since you received the certificates? This is not true if you moved after this fact.

0
source

All Articles