httpswindows-serviceswcf-securitywebhttpbinding

How to disable credentials input for HTTPS call to my WCF hosted in windows service


I'm just creating my first WCF project, so I have a lot of deficiencies in knowledge in this field. My problem is that when I'm calling my WCF url in web browser, I have to enter the credentials but I cannot even use my domain name and password, but I have to choose my personal chip card certificate and enter it's password. After that, everything work like a charm.

My final product should be installed on every user workstation in our domain for IT operations purposes only. So there will be some AD authorization after that. About certificate... We have our own company root CA certificate, and every workstation have it's own certificate which is it's grandchild:

Example of our certificate tree:

COMPANYROOTCA >> COMPANYSUBCA1 >> WORKSTATIONNAME.DOMAIN (this one is used as WCF service cert)

This is what I have right now for hosting the WCF in my Windows service running under NetworkService Account:

        serviceHost.Dispose(); //extension for close() and set to null

        Uri httpsUrl = new Uri("baseAdress");
        serviceHost = new ServiceHost(typeof(Service.myService), httpsUrl);

        WSHttpBinding wsHttpBinding = new WSHttpBinding();
        wsHttpBinding.Security.Mode = SecurityMode.Transport;
        wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
        wsHttpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;

        WebHttpBinding webHttpBinding = new WebHttpBinding();
        webHttpBinding.Security.Mode = WebHttpSecurityMode.Transport;
        webHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
        webHttpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;

        ServiceMetadataBehavior smb = new ServiceMetadataBehavior
        {
            HttpGetEnabled = false,
            HttpsGetEnabled = true,      
        };

        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection collection = store.Certificates;
        X509Certificate2 cert = collection.OfType<X509Certificate2>().First(c => c.SubjectName.Name == "CN=WorkstationName.Domain");
        store.Close();

        serviceHost.Credentials.ServiceCertificate.Certificate = cert;           

        ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior
        {
            MaxConcurrentCalls = 16,
            MaxConcurrentInstances = 26,
            MaxConcurrentSessions = 10
        };
        serviceHost.Description.Behaviors.Add(throttleBehavior);

        ServiceEndpoint soapEndpoint = serviceHost.AddServiceEndpoint(typeof(Contract.IMyService), wsHttpBinding, "soap");
        ServiceEndpoint restEndpoint = serviceHost.AddServiceEndpoint(typeof(Contract.IMyService), webHttpBinding, "rest");
        ServiceEndpoint mexEndpoint = serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpsBinding(), "mex");

        restEndpoint.Behaviors.Add(new WebHttpBehavior());

        tempAdminHost.Open();

So my question is: Is there any way, how to, for example, automaticaly get domain account which use the browser and call the url or any alternative how to still use HTTPS but without putting any credentials?


Solution

  • I didn’t see the way you use the credential to authenticate the client. the client credential type of the two endpoints you use to host the service are None. How does the browser ask you to input the credential? Besides, by default, If the server set up the ClientCredentialType to Windows, the client would use the current user as the credential. The current user’s password and account will be default credential when need to provide a credential.
    One more thing to note, if you are simply prompted in the browser to select a certificate instead of the credential(user/password), as follows,
    enter image description here
    We may have configured the following parameter(clientcertnegotiation parameter).

    netsh http add sslcert ipport=127.0.0.1:8000 certhash=c20ed305ea705cc4e36b317af6ce35dc03cfb83d appid={c9670020-5288-47ea-70b3-5a13da258012} clientcertnegotiation=enable
    

    Because the way you use to provide a certificate to encrypt the communication is not correct.

    serviceHost.Credentials.ServiceCertificate.Certificate = cert; 
    

    We need to bind the certificate to Port.
    https://learn.microsoft.com/en-us/windows/desktop/http/add-sslcert
    when hosting the service in IIS, we accomplish it by the below UI.
    enter image description here
    And the parameter configuration depends on the below.
    enter image description here
    enter image description here
    So I suspect the process that binds the certificate to the specified port is completed by IIS. and the parameter should be ignored.
    Feel free to let me know if there is anything I can help with.