I'm trying to connect to a WCF service from a WinForms client using an IIS-generated self-signed certificate, but no matter what I do I always get "Could not establish trust relationship for the SSL/TLS secure channel with authority ...".
My Web.config looks like this:
...
<binding name="BasicHttpBinding_TransportCertificate">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
...
<endpoint address="transportCertificate" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_TransportCertificate"
name="TransportCertificateEndpoint" contract="MyService"/>
My client code looks like this:
private void Ping(string endpointAddress)
{
var binding = new BasicHttpContextBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var service = new CMServiceReference.CMServiceClient(binding,
new EndpointAddress(string.Format("{0}/{1}", endpointAddress, "transportCertificate")));
service.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySubjectName,
"server.domain.com");
service.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
service.Ping();
}
Setting the certificate, which has been installed on the client machine, seems to work just fine, but I still always get that same error when calling service.Ping(). I've played around with the CertificateValidationMode options, but none of those seem to make any difference.
Is there something obvious I'm missing?
EDITS BELOW AFTER RESOLVING ISSUE
It turns out that the self-signed certificate was in the wrong store on the client the whole time. It needed to be in Local Machine/Trusted Root Certification Authorities. After that it works fine without "Certificate" being specified on the WCF attribute.
After placing the cert in the right location, I simply updated my Web.config to like like so:
...
<binding name="BasicHttpBinding_TransportCertificate">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
...
<endpoint address="transportCertificate" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_TransportCertificate"
name="TransportCertificateEndpoint" contract="MyService"/>
and my client code to like like this:
private void Ping(string endpointAddress)
{
var binding = new BasicHttpContextBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
var service = new CMServiceReference.CMServiceClient(binding,
new EndpointAddress(string.Format("{0}/{1}", endpointAddress, "transportCertificate")));
service.Ping();
}