How to set WCF protection to request a client certificate?

I have a WCF service. I require certificate authentication from clients. This is the service configuration:

<system.serviceModel> <services> <service name="FilmLibrary.FilmManager" behaviorConfiguration="FilmService.Service1Behavior"> <endpoint address="manager" name="certBinding" binding="basicHttpBinding" contract="FilmContract.IFilmManager" /> </service> </services> <bindings> <basicHttpBinding> <binding name="certBinding"> <security mode="Message"> <message clientCredentialType="Certificate" /> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="FilmService.Service1Behavior"> <serviceCredentials> <clientCertificate> <authentication trustedStoreLocation="LocalMachine" certificateValidationMode="PeerTrust" /> </clientCertificate> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration> 

Public Key Installed in LocalMachine, Trusted People

Client configuration is as follows:

 <system.serviceModel> <bindings> <basicHttpBinding> <binding name="certBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="Message"> <message clientCredentialType="Certificate"/> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="certBehaviour"> <clientCredentials> <clientCertificate findValue="SubjectKey" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> <client> <endpoint address="[...]/Service1.svc/manager" binding="basicHttpBinding" bindingConfiguration="certBinding" behaviorConfiguration="certBehaviour" contract="FilmsService.IFilmManager" name="certBinding" /> </client> </system.serviceModel> 

The private key is set in the Personal, current user.

Without security, the service works. With security enabled, no. I tried several configurations and I was having errors, such as authentication, or that I have to set the service certificate in the clientCredentials element. Which I do not understand, because I do not want to fully authenticate the service.

+4
source share
3 answers

Instead

  <serviceCredentials> <clientCertificate> <authentication trustedStoreLocation="LocalMachine" certificateValidationMode="PeerTrust" /> </clientCertificate> </serviceCredentials> 

I think you should have

  <serviceCredentials> <serviceCertificate findValue="SubjectKey" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/> </serviceCredentials> 

You do not authenticate this service; instead, you tell the service how the client should be authenticated.

+2
source

I found the following guide extremely helpful and very detailed. https://notgartner.wordpress.com/2007/09/06/using-certificate-based-authentication-and-protection-with-windows-communication-foundation-wcf/

It covers creating a service, client, certificates, and setting up 2 configurations.

Server:

 <bindings> <basicHttpBinding> <binding name="secureHttpBinding"> <security mode="TransportWithMessageCredential"> <message clientCredentialType="Certificate" /> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <clientCertificate> <!--only accept certificates in "Trusted People"--> <authentication certificateValidationMode="PeerTrust" trustedStoreLocation="LocalMachine" /> </clientCertificate> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> 

Customer:

 <bindings> <basicHttpBinding> <binding name="customBinding1"> <security mode="TransportWithMessageCredential"> <message clientCredentialType="Certificate" /> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="customBehavior1"> <clientCredentials> <!--fabrkam--> <clientCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindByThumbprint" findValue="d2 31 6a 73 1b 59 68 3e 74 41 09 27 8c 80 e2 61 45 03 b1 7e"/> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> 

We automatically redirect any HTTP requests to HTTPS, so we must use the TransportWithMessageCredential security. For normal Http, using just Message, like a security type, should also work.

+3
source

I was able to accomplish the same thing using customBinding, for example:

  <customBinding> <binding name="bindingName"> <security authenticationMode="UserNameOverTransport" /> <httpsTransport requireClientCertificate="true"/> </binding> </customBinding> 

(I skipped attributes that are not relevant to your case.)

As for authenticationMode , I think you can probably use any of them - here httpsTransport with requireClientCertificate are important parts.

+2
source

All Articles