Click here to Skip to main content
15,881,380 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I created a self-hosted WCF service and client on 2 different development machines on a LAN, and used basicHttpBinding in order to test connectivity and functionality. The tests were successful.

My goal is to use wsHttpBinding with TransportWithMessageCredential security, and clientCredentialType certificate.

I thus created the following app.config file for the service:

XML
<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerTrust"/>
            </clientCertificate>            
            <serviceCertificate findValue="WCFServer" 
                      storeLocation="LocalMachine" 
                      storeName="My" 
                      x509FindType="FindBySubjectName"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
      <binding name="wsHttpEndpointBinding">
        <security mode="TransportWithMessageCredential">
        <message clientCredentialType="Certificate"/>
        </security>
      </binding>
      </wsHttpBinding>
    </bindings>    
    <services>
      <service name="WCFServiceHost.Operations" behaviorConfiguration="ServiceBehavior">
        <endpoint name="wsHttpEndpoint" address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"   contract="WCFServiceHost.IOperations">
        </endpoint>              
        <endpoint name="mexHttpEndpoint" address="mex" binding="mexHttpsBinding" contract="IMetadataExchange">
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="https://10.0.0.103:8003/WCFServiceHost/Operations/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>


I created 2 certificates (WCFServer and WCFClient) on the server in accordance with
...codeproject.com/Articles/36683/9-simple-steps-to-enable-x-509-certificates-on-wcf
and exported the WCFClient certificate on the server machine, and imported it on the client machine.

I also added the ssl certificate binding on the server machine using netsh.

I am able to create an instance of the ServiceHost with Service, with the modified app.config.

I created the following app.config for the client:

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EndpointBehavior">
          <clientCredentials>
            <clientCertificate storeLocation="LocalMachine"
                       storeName="My"
                       x509FindType="FindBySubjectName"
                       findValue="WCFClient" />
            <serviceCertificate>
              <authentication certificateValidationMode="PeerTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>    
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
            receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
            transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
            allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
            enabled="false" />
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="Certificate" negotiateServiceCredential="true"
              algorithmSuite="Default" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://10.0.0.103:8003/WCFServiceHost/Operations/"
          binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
          contract="WCFService.IOperations" name="wsHttpEndpoint">
        <identity>
          <dns value="WCFServer" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>


I then updated the Service Reference.
The update procedure issued a Security Alert, which is most likely related to the subsequent issue described below, and which I have not been able to resolve.

I ignored the Security Alert and continued. The Service Reference was updated.

I then executed the client, and received this error:

"The client certificate is not provided. Specify a client certificate in ClientCredentials."

After stepping through code, I noticed on "client = new WCFService.Client();" that the value of client.ClientCredentials.ClientCertificate.Certificate = null.

I then added the following in code after "client = new WCFService.Client();":

C#
X509Store store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
foreach (X509Certificate2 x509 in collection)
{
	if (x509.Thumbprint == "236D7D4AD91234B8F22D3781D61AACB56788E1B5")
	{
		client.ClientCredentials.ClientCertificate.SetCertificate(
			x509.SubjectName.Name, store.Location, StoreName.My);
	}
}


After execution of this code, client.ClientCredentials.ClientCertificate.Certificate contains the certificate.

Upon executing "client.Open();" , an exception is thrown with the following contents.

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
The remote certificate is invalid according to the validation procedure.
Could not establish trust relationship for the SSL/TLS secure channel with authority

If anyone with knowledge of how I may approach resolution of the above issues can assist, I will be most grateful.

Thank you, Ol.
Posted

1 solution

Well, it's a bit late but establishSecurityContext="true" might be the solution.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900