I am trying to use SSL certificate authentication in WCF/.NET version 4.0 IIS version 7.5, but, when I enable the oneToOneMappings authentication, the system does not recognize the maxReceivedMessageSize, when I comment out the oneToOneMappings authentication section, IIS recognize the maxReceivedMessageSize variable.
Any ideas about how to make this WCF service use the maxReceivedMessageSize value that I set when the SSL certificate authentication is enabled?
Service Model section:
<system.serviceModel>
<services>
<service behaviorConfiguration="AServiceBehavior" name="<IContract>">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="MutualSslBinding" contract="<IContract>" name="AnEndpoint" />
<host><baseAddresses><add baseAddress="https://asite.com/service" /></baseAddresses></host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="AServiceBehavior">
<serviceCredentials>
</serviceCredentials>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true" />
<serviceSecurityAudit auditLogLocation="Security" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="MutualSslBinding" axReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport"> <transport clientCredentialType="Certificate" /></security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true">
</serviceHostingEnvironment>
</system.serviceModel>
Certificate Security section:
<system.webServer>
<security>
<access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />
<authentication>
<anonymousAuthentication enabled="true" />
<basicAuthentication enabled="false" />
<clientCertificateMappingAuthentication enabled="false" />
<digestAuthentication enabled="false" />
<windowsAuthentication enabled="false" />
<iisClientCertificateMappingAuthentication enabled="true" oneToOneCertificateMappingsEnabled="true" manyToOneCertificateMappingsEnabled="true">
<oneToOneMappings>
<clear />
<add userName="<LocalUser>" password="<EncryptedPassword>" certificate="<Authentication certificate text>" />
</oneToOneMappings>
</iisClientCertificateMappingAuthentication>
</authentication>
</security>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="false" />
</system.webServer>
On this specific case the issue was not related to the WCF configuration but to the uploadReadAheadSize setting in IIS.
TLS Overhead
When you are using SSL Certificate Authentication the overhead of your request can increase the size to more than 49Kb on the authentication process.
Returning the error 413 Entity Too Large
Use uploadReadAheadSize to control the allowed request size for IIS.
First verify the IIS Request Filtering.
To do this, open IIS Manager. Select your application. In the Features view you will see “Request Filtering”. Open this feature and on the right hand panel you will find “Edit Feature Settings”
Maximum Allowed Content Length is an Optional U-Int attribute. It specifies the maximum length of content in a request, in bytes. The default value is 30000000, which is approximately 28.6MB.
Next, we can set the uploadReadAheadSize in IIS.
To navigate to this setting, use the following steps:
Launch "Internet Information Services (IIS) Manager"
Expand the Server field
Expand Sites
Select the site your application is in.
In the Features section, double click "Configuration Editor"
Under "Section" select: system.webServer>serverRuntime
The default setting value is 49Kb.
Response provided by Wanjun Dong at MSDN
serverRuntime settings
Related
I'm trying to consume a WCF service, hosted in a shared server. it works perfectly with SOAPUI, but when i tried to do it with my vb.net application it give me this error:
the http request is unauthorised with client authentication scheme
"anonymous".
I tried a lot of solutions, changing the app.config of my application, adding security mode="TransportCredentialOnly", with clientCredentialType="Windows" and "NTLM", and it only changes the last part of the error, giving "Negotiate" with "anonymous".
here how i add security in app.config
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
I think this is an application problem because, as I said before, it works perfectly in SOAPUI, I don't know if I need to add something more.
The web.config of WCF:
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime maxRequestLength ="262144" executionTimeout="103600"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpErrors errorMode="Detailed"/>
</system.webServer>
EDIT:
I just receive an answer from server's provider and he said that there's a program, ModSecurity, that is blocking me access to WCF until i add a correct content header and user agent. How can i add it to the call?
UPDATE:
I used the answer of GMan80013 and now i'm stuck in this part.
I'm getting this error "Coul not load type 'Microsoft.ServiceModel.Dispatcher.HttpUserAgentBehaviorExtensionElement, SolutionPruebas.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' registered for the extension 'httpUserAgent'".
This error come from this part, I assume:
<behaviorExtensions>
<add name="httpUserAgent" type="Microsoft.ServiceModel.Dispatcher.HttpUserAgentBehaviorExtensionElement, SolutionPruebas.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</behaviorExtensions>
Or from here.
<behaviors>
<endpointBehaviors>
<behavior name="LegacyServiceEndpointBehavior">
<httpUserAgent userAgent="test user agent" />
</behavior>
</endpointBehaviors>
I have WCF service with windows authentication. After deploying it to another server I received the following exception:
System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized
The client configuration doesn't changed and looks like this:
<ws2007HttpBinding>
<binding name="autoSecureBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""></transport>
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="false"/>
</security>
</binding>
</ws2007HttpBinding>
EDIT: When I open my service in browser I receive the following error:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
Does anybody know what could be the problem?
Is another server under the same active directory domain?
Also You want to go to target IIS and see if Site / Application Authentication settings have "Windows Authentication" set to "Enabled". (See screens for IIS7 below)
Here is a working web.config of a Win auth only WCF service that I am using (Only Windows Authentication is enabled in IIS).
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="MyBindingForWindowsAuth">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
<!--<transport clientCredentialType="Windows" />-->
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="DataAccessService.Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBindingForWindowsAuth" contract="DataAccessService.IService" />
<endpoint address="mex" binding="basicHttpBinding" bindingConfiguration="MyBindingForWindowsAuth" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
With this setup in place, if you want to pass ASP.NET user identity to WCF you have 3 options:
Option 1:
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("phil.morris", "P4ssW0rd", "mydomain");
Option 2:
Use impersonate:
using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
string s = client.GetUserInfo();
retVal = "Wcf User: " + s;
}
Option 3:
ENABLE ASP.NET Impersonation in the caller ASP.NET application
Im trying to host my SSL WCF service locally on my PC (IIS 7) and for some reason i cant connect to it. What i need is to use SSL and send in credntials to authenticate the user before calling some function.
When i connect to it, i get There was no endpoint listening at https://[computer name]/YYY.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
the inner message is The remote server returned an error: (404) Not Found.
What i have noticed is that when i access the WSDL (hosted over https) the endpoint address is not http*S* and i think that is why my service is probably failing.
here is part of my WSDL
<wsdl:service name="WSNAME">
<wsdl:port name="WSHttpBinding_INams" binding="tns:WSHttpBinding_INams">
<soap12:address location="http://[computer name]/YYY.svc" />
<wsa10:EndpointReference>
<wsa10:Address>http://[computer name]/YYY.svc</wsa10:Address>
<Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<Spn>host/[computername]</Spn>
</Identity>
</wsa10:EndpointReference>
This is my service config file
<service behaviorConfiguration="test" name="NewServiceType">
<endpoint address="https://[computer name]/YYY.svc" binding="wsHttpBinding"
bindingConfiguration="WsBinding" name="WS" contract="Authentication2.INams" />
<endpoint address="mex" binding="mexHttpBinding" name="MX" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://[computer name]/XXX.svc" />
</baseAddresses>
</host>
can anyone point out what am i doing wrong?
my web.config
<system.serviceModel>
<protocolMapping>
<remove scheme="http" />
<add scheme="http" binding="wsHttpBinding" />
</protocolMapping>
<bindings>
<wsHttpBinding>
<binding name="wsbinding">
<security mode="TransportWithMessageCredential">
<transport proxyCredentialType="Basic" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="NewServiceType">
<endpoint address="/WS" binding="wsHttpBinding"
bindingConfiguration="wsbinding" name="WS" contract="Authentication3.IService1" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="MX" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"
httpsGetUrl="https://[computerName]/Service1.svc" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
FOUND IT !!
WCF service returns 404 over https but not http
the problem is that my service element name was what the editor adds by default "MyNewService" or whatever the default name is. You HAVE to use the fully qualified name..
<services>
<service name="[Namespace].[service class name]">
This cost me over 2 long days of constant work and research. If this works for you, please vote that guys answer up - NO ONE has ever mentioned this point .. i couldnt because im still new
Your endpoint has a bindingConfiguration attribute defined of WsBinding. There should be a section of the web.config that defines this configuration, including the security mode to be used (presumably transport or transportWithMessageCredential if you want to use SSL).
For example:
<bindings>
<wsHttpBinding>
<binding name="WsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Additionally you'll need to configure IIS with a binding listening on 443, referencing an appropriately named SSL certificate.
For a credential type of windows:
This corresponds to integrated Windows authentication in IIS. When set
to this value, the server is also expected to exist on a Windows
domain that uses the Kerberos protocol as its domain controller.
More details on this on the MSDN WCF transport security page
Alternatively you can use TransportWithMessageCredential. This uses SSL to encrypt the connection, and the credentials are passed in the message itself (effectively username and password in the SOAP header). In that case your binding configuration looks more like:
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Username" />
</security>
You then need to define a password validator behavior on the service to check the user and password. Here's some more info on that: http://msdn.microsoft.com/en-us/library/aa354508.aspx
The client machine has the "TicketSalesClient" certificate in "My" storage of current user and the "TicketSalesServer" certificate in "TrustedPeople" storage of current user. The server machine has "TicketSalesClient" certificate in "TrustedPeople" storage of local machine and the "TicketSalesServer" certificate in "My" storage of local machine.
The service runs under IIS 7. Below is the web.config file:
<system.serviceModel>
<services>
<service behaviorConfiguration="secureBehavior" name="InternetRailwayTicketSales.TicketSalesImplementations.TicketSalesService">
<endpoint address="TicketSalesService"
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding" contract="InternetRailwayTicketSales.TicketSalesInterface.ITicketSales" />
<endpoint address="TicketSalesServiceSecureMex"
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:443/TicketSales/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceThrottling maxConcurrentInstances="5000" maxConcurrentSessions="5000" />
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<serviceCertificate findValue="TicketSalesServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
The service in IIS is configured for SSL and certificate requiring.
1)Now when I try to add service reference in the client I receieve: "The HTTP request was forbidden with client authentication scheme 'Anonymous'. The remote server returned an error: (403) Forbidden."
2)If I try to request the metadata endpoint using browser I firstly apply the SSL certificate and then receieve an error that "The credentials do not give the right to view this directory or page." As I understand this is because I can't give the client credentials through the browser.
3)I tried to use svcutil with configuration file which contains client credentials:
<configuration>
<system.serviceModel>
<client>
<endpoint
behaviorConfiguration="ClientCertificateBehavior"
binding="basicHttpBinding"
bindingConfiguration="Binding1"
contract="IMetadataExchange"
name="https" />
</client>
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<clientCertificate findValue="TicketSalesClient"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And then:
svcutil https://veryLongAddress.svc?wsdl /config:svcutilConf.config
And the response is that the "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"
So what am I doing wrong?
Seems like your certificates installation is fine. Can you try as shown below and see the output. Try to browse to the service from IE and you should be able to see the service and its wsdl.
Go to IE and then
Tools --> Internet Options --> Security --> Internet --> Custom Level
Tools --> Internet Options --> Security --> Intranet --> Custom Level
Now scroll down to Misc section to find the option "Dont Prompt for client certificate selection when no certificate is present or only one certificate is present" to Diable.
Now restart IE and browse to the service and IE should ask you to select a client certificate from the personal store and you need to select mvc.localhost.
If TicketSalesClient cert is not visible then your client certificate is not in the appropriate store.
The reason for this is that the file you are using to install the certificates do matter as well as the purpose for which the certificate has been created. You can find the purpose of each certificate when you double click them in the certificate store you have a column that is called Intended Purpose. Make sure its for your client certificate.
When hosting the service in IIS all endpoints must have the same transport security configuration. I played with this before and I ended with redefining binding for WSDL GET (yes it has also internal binding defined). So modify your bindings on service to:
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
<customBinding>
<binding name="wsdlBinding">
<textMessageEncoding messageVersion="None" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
And in service behaviors use:
<serviceMetadata httpsGetEnabled="true"
httpsGetBinding="customBinding"
httpsGetBindingConfiguration="wsdlBinding" />
This should force WSDL get to require client certificate and it "should" work from browser (unless there is some other problem).
When we host WCF service in IIS with security type transport and client credential type certificate, Then put your client certificate on Root store and enable anonymous authentication in IIS. Enable anonymous authentication in IIS But most important, add your certificate to root store.
I'm looking for a definitive answer as to whether what I'm trying to do is supported or not.
Basically, I'm using WCF to stream large MTOM attachments (200 Mb), this works perfectly fine. The security requirements for the service is to use HTTPS and certificate-based authentication. I can run the service over HTTPS without any problems, but once I set IIS to “Accept client certificates” or “Require client certificates” (no change in the code), the following error is thrown (but only once the attachments get over about 80 Mb or so):
The socket connection was aborted.
This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.
Local socket timeout was '00:30:00'.
I found some resources, sorry can't find them now, that indicated that the failure is probably related to the fact that the incoming messages either cannot be digitally signed, or verified due to the streaming nature of the message contents. I believe the service would have to hash the whole message contents to verify the cert, but this can't be achieved because portions of the message are in transit while validation is trying to occur.
I've setup the message contract so that the body is a single Stream element, and the other elements are contained within the header:
<MessageContract()>
Public Class StreamAttachmentRequest
<MessageHeader(MustUnderstand:=True)>
Public Property AttachmentName As String
<MessageBodyMember(Order:=1)>
Public Property Attachment As Stream
End Class
The service configuration looks as follows:
<system.serviceModel>
<!-- BINDING -->
<bindings>
<basicHttpBinding>
<binding name="TestCaseBasicBinding"
messageEncoding="Mtom"
transferMode="StreamedRequest"
maxReceivedMessageSize="2147483647"
closeTimeout="00:30:00"
openTimeout="00:30:00"
receiveTimeout="00:30:00"
sendTimeout="00:30:00">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
<readerQuotas maxDepth="32"
maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
<!-- BEHAVIORS -->
<behaviors>
<serviceBehaviors>
<!-- TEST CASE SECURE BEHAVIOR -->
<behavior name="TestCaseSecureBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<serviceCertificate
storeLocation="LocalMachine"
storeName="My"
findValue="DistinguishedNameOfCert"
x509FindType="FindBySubjectDistinguishedName" />
<clientCertificate>
<authentication certificateValidationMode="ChainTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<!-- SERVICES -->
<services>
<service name="StreamingMutualAuthTestCase.Web.Service.TestCaseServiceImplementation"
behaviorConfiguration="TestCaseSecureBehavior">
<!-- SERVICE -->
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="TestCaseBasicBinding"
contract="StreamingMutualAuthTestCase.Web.Service.ITestCaseService" />
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
The client configuration looks like this:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ITestCaseService" closeTimeout="00:30:00"
openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
maxReceivedMessageSize="2147483647" messageEncoding="Mtom"
transferMode="Streamed">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" realm="" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<!-- BEHAVIORS -->
<behaviors>
<endpointBehaviors>
<behavior name="SecureClientBehavior">
<clientCredentials>
<clientCertificate
storeLocation="LocalMachine"
storeName="My"
findValue="DistinguishedNameOfCert"
x509FindType="FindBySubjectDistinguishedName"/>
<serviceCertificate>
<authentication certificateValidationMode="ChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="https://test7/TestCaseService/TestCaseService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ITestCaseService"
contract="TestCaseService.ITestCaseService"
name="BasicHttpBinding_ITestCaseService"
behaviorConfiguration="SecureClientBehavior"/>
</client>
</system.serviceModel>
Once again, this will work just fine until I set IIS Client Certs to either Accept or Require.
Also, there is a 413 error in the IIS log...
2011-08-18 15:00:06 W3SVC1 10.39.8.111 POST /TestCaseService/TestCaseService.svc - 443 - 10.75.13.81 - - - test7 413 0 0
I've already designed an authentication service on top of my file upload service to work around the issues; but I'd really like to know if what I'm trying to do is 'do-able' or not.
Thanks a ton - Patrick
If you want to turn on client certificates in IIS you must do the same for your service (and client):
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
Your client must provide certificate to the proxy:
yourProxy.ClientCredentials.ClientCertificate.SetCertificate(...);
Also your server must trust these certificates so client certificates must be either issued by certification authority trusted by the server or they must be installed to LocalMachine\Trusted people store directly on the server.
WCF endpoints don't support "Accept client certificates" - you must either use client certificates or not.