Question

My service works fine over http using the following code:

WebServiceHost serviceHost = new WebServiceHost(typeof(RestInterface), new Uri(http://localhost/rest));
serviceHost.Open();

When I try to host the exact same service over https it doesn't work. I get nothing in Service Trace Viewer and Chrome just says "This web page is not available". Here is the code I use for https:

var serviceHost = new WebServiceHost(typeof(RestInterface), new Uri(https://localhost/rest));

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");

var binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;

var ep = serviceHost.AddServiceEndpoint(typeof(IRestInterface), binding, "");
ep.EndpointBehaviors.Add(new WebHttpBehavior());

serviceHost.Open();

Has anyone gotten this working? What am I doing wrong?!?

Was it helpful?

Solution

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();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top