none
WebHttpBinding, TransportSecurity, Client Certificates RRS feed

  • Question

  • So, I have a RESTful service (HTTPS, WebHttpBinding) and I want to allow only a few users to be able to access it with their e-tokens.

    When I configure it in the following way:

    			var baseAddress = new Uri("https://samantha-alias:8001/");
    
    			var binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
    			binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
    			var endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IKeyManagerService), typeof(KeyManagerService)), binding, new EndpointAddress(baseAddress));
    
    			var serviceHost = new WebServiceHost(typeof(KeyManagerService), baseAddress);
    			serviceHost.AddServiceEndpoint(endpoint);
    
    			serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
    

    the service works, but grants access to any client certificate sighed by our corporate root cert authority, even to those certs, that are not placed in Local Computer->Trusted People store (although I don't expect that by specifying X509CertificateValidationMode.PeerTrust).

    So, it seems that with this configuration the client certs are still validated with the default ChainTrust mode.

    OK, this might be so because client cert validation is not supported by WCF together with transport security (other guys have already noted that, e.g. here: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/6b2d6fca-7a0d-49e4-87ca-65e6b2529d4c/). A bit strange though is that the service starts and works fine with that "invalid" config, instead of throwing any exceptions.

    So, I've found a workaround for that, by specifying X509CertificateValidationMode.Custom and manually providing a peer-trust cert validator, which is included with WCF:

    //			serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
    			serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
    			serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = X509CertificateValidator.PeerTrust;
    

    And voila! It seems to work now! The service allows acces only when I manually put the public part for a e-token cert into Local Computer->Trusted People on the server.

    And my question is: what am I missing? :)

    Why the first config is considered invalid for WCF and why my second config seems to be valid and works? Does the second config really provide the security mode I'm looking for or there still might be any discrepancies in the communication between WCF and http.sys? Does anyone know, how it all works internally?

    I'm asking this question, because the service I'm working on really needs to be secure enough. So I don't want to make a mistake because of misunderstanding.

    Tuesday, May 28, 2013 2:50 PM

Answers

  • Hi, seems that you have found the solution for the issue by using a custom mode. As you said, "certificateValidationMode=xxx" you configured in service/endpoint behavior is specific to message security, not for transport security.
    Wednesday, May 29, 2013 6:53 AM