Configuring WCF for client certificate authentication

Below the steps to follow if you need to connect an IIS hosted WCF client to a IIS hosted WCF server via a WSHttpBinding with transport security using client certificates.

On the server implement your service and configure like the following...

   1: <system.serviceModel>
   2:  <behaviors>
   3:    <endpointBehaviors />
   4:    <serviceBehaviors>
   5:      <behavior name="MyBehavior">
   6:        <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
   7:        <serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
   8:        <serviceCredentials>
   9:          <clientCertificate>
  10:            <authentication mapClientCertificateToWindowsAccount="true" />
  11:          </clientCertificate>
  12:        </serviceCredentials>
  13:      </behavior>
  14:    </serviceBehaviors>
  15:  </behaviors>
  16:  <bindings>
  17:    <wsHttpBinding>
  18:      <binding name="wshttpconfig" messageEncoding="Mtom">
  19:        <readerQuotas maxArrayLength="16384000" />
  20:        <security mode="Transport">
  21:          <transport clientCredentialType="Certificate" />
  22:        </security>
  23:      </binding>
  24:    </wsHttpBinding>
  25:  </bindings>
  26:  <services>
  27:    <service behaviorConfiguration="MyBehavior" name="MyWCF">
  28:      <endpoint address=""
  29:        binding="wsHttpBinding"
  30:        bindingConfiguration="wshttpconfig" contract="IMyWCF" />
  31:    </service>
  32:  </services>
  33: /system.serviceModel>

The important thing is on line  21 to tell WCF that the crendential are provided by a client certificate.

I also set messageEncoding="Mtom", but you can leave the default value for this property.

In IIS manager if you don't want to manually configure certificate mapping you can use Directory Service Mapping.

With this in place, enable client certificate. If you enabled directory service mapping don't bother with certificate mapping.

As stated in my previous post enable anonymous logon (with a wrong identity) to make WCF work.

On the client add service reference to the previously created service.

Configure the client as follow:

   1: <system.serviceModel>
   2:  <client>
   3:    <endpoint address="https://myServer/MyService3/MyWCF.svc"
   4:      binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyWCF1"
   5:      behaviorConfiguration="clientEndpointCredential"
   6:      contract="MyService.IMyWCF" name="WSHttpBinding_IMyWCF1" />
   7:  </client>
   8:  <behaviors>
   9:    <endpointBehaviors>
  10:      <behavior name="clientEndpointCredential">
  11:        <clientCredentials>
  12:          <clientCertificate storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="MyClientCertificateName" />
  13:        </clientCredentials>
  14:      </behavior>
  15:    </endpointBehaviors>
  16:    <serviceBehaviors/>
  17:  </behaviors>
  18:  <bindings>
  19:    <wsHttpBinding>
  20:      <binding name="WSHttpBinding_IMyWCF1" closeTimeout="00:01:00"
  21:        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
  22:        bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
  23:        maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom"
  24:        textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
  25:        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  26:          maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  27:        <reliableSession ordered="true" inactivityTimeout="00:10:00"
  28:          enabled="false" />
  29:        <security mode="Transport">
  30:          <transport clientCredentialType="Certificate" proxyCredentialType="None"
  31:            realm="" />
  32:        </security>
  33:      </binding>
  34:    </wsHttpBinding>
  35:  </bindings>
  36: </system.serviceModel>

the important part is on line 5 to set what certificate the client should use. Beware that the certificate must be in the computer certificate store and accessible from the IIS app where the client is hosted.

If you get in trouble with certificates try enabling WCF logs (web_messages.svclog and web_tracelog.svclog) reading them with SvcTraceViewer.exe

and System.net logs (trace.log) reading them with your preferred text viewer .

   1: <system.diagnostics>
   2:   <trace autoflush="true"/>
   3:   <sources>
   4:     <source name="System.Net" maxdatasize="1024">
   5:       <listeners>
   6:         <add name="TraceFile"/>
   7:       </listeners>
   8:     </source>
   9:     <source name="System.Net.Sockets" maxdatasize="1024">
  10:       <listeners>
  11:         <add name="TraceFile"/>
  12:       </listeners>
  13:     </source>
  14:     <source name="System.ServiceModel" switchValue="Warning, ActivityTracing"
  15:       propagateActivity="true">
  16:       <listeners>
  17:         <add type="System.Diagnostics.DefaultTraceListener" name="Default">
  18:           <filter type="" />
  19:         </add>
  20:         <add name="ServiceModelTraceListener">
  21:           <filter type="" />
  22:         </add>
  23:       </listeners>
  24:     </source>
  25:     <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
  26:       <listeners>
  27:         <add type="System.Diagnostics.DefaultTraceListener" name="Default">
  28:           <filter type="" />
  29:         </add>
  30:         <add name="ServiceModelMessageLoggingListener">
  31:           <filter type="" />
  32:         </add>
  33:       </listeners>
  34:     </source>
  35:   </sources>
  36:   <sharedListeners>
  37:     <add initializeData="D:\MyLog\web_tracelog.svclog"
  38:       type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  39:       name="ServiceModelTraceListener" traceOutputOptions="DateTime, Timestamp, ThreadId">
  40:       <filter type="" />
  41:     </add>
  42:     <add initializeData="D:\MyLog\web_messages.svclog"
  43:       type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  44:       name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
  45:       <filter type="" />
  46:     </add>
  47:     <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="D:\MyLog\trace.log"/>
  48:   </sharedListeners>
  49:   <switches>
  50:     <add name="System.Net" value="Verbose" />
  51:     <add name="System.Net.Sockets" value="Verbose" />
  52:   </switches>
  53: </system.diagnostics>

Hope this helps someone

«gennaio»
domlunmarmergiovensab
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789