Ok, I finally figured it out. I need to bind the cert to the port. Don't do:
serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.Custom;
serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator =
new CertValidator(); // Custom validator that will accept any cert
serviceHost.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"localhost");
instead do:
Process bindPortToCertificate = new Process();
bindPortToCertificate.StartInfo.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "netsh.exe");
bindPortToCertificate.StartInfo.Arguments = string.Format("http add sslcert ipport=0.0.0.0:{0} certhash={1} appid={{{2}}}", epAddress.Port, cert.Thumbprint, Guid.NewGuid());
bindPortToCertificate.Start();
bindPortToCertificate.WaitForExit();
Taken from: http://blogs.msdn.com/b/james_osbornes_blog/archive/2010/12/10/selfhosting-a-wcf-service-over-https.aspx
Here is my working code. It still needs to be cleaned up a bit:
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
serviceHost = new ServiceHost(typeof(RestInterface));
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
var cert = store.Certificates.Find(X509FindType.FindBySubjectName, "localhost", false)[0];
store.Close();
Process bindPortToCertificate = new Process();
bindPortToCertificate.StartInfo.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "netsh.exe");
bindPortToCertificate.StartInfo.Arguments = string.Format("http add sslcert ipport=0.0.0.0:{0} certhash={1} appid={{{2}}}", epAddress.Port, cert.Thumbprint, Guid.NewGuid());
bindPortToCertificate.Start();
bindPortToCertificate.WaitForExit();
var ep = serviceHost.AddServiceEndpoint(typeof(IRestInterface), binding, epAddress);
ep.EndpointBehaviors.Add(new WebHttpBehavior());
serviceHost.Open();