Yury
Yury

Reputation: 57

WCF https with only server certificate

I trying to do WCF using self-signed certificate. I found some solutions,but they need client to know clinet certificate before connection. I would like make client works as browser(When browser use web server certificate). I mean browser don't know webserver's certificate before connection, it can obtain it from web server. My server's web.config:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <services>
      <service behaviorConfiguration="security" name="WebApplicationExchange.UKService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="security" contract="WebApplicationExchange.IUKService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost/UKService/UKService.svc" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="security">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceAuthorization.PasswordValidator,ServiceAuthorization" />
            <windowsAuthentication allowAnonymousLogons="false" />
          </serviceCredentials>
          <serviceAuthorization principalPermissionMode="Custom">
            <authorizationPolicies>
              <add policyType="ServiceAuthorization.AuthorizationPolicy,ServiceAuthorization" />
            </authorizationPolicies>
          </serviceAuthorization>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="security">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

It works fine with web browsers.

But client show error: Could not establish trust connection for secure channel SSL / TLS with authority "localhost: 56389". Client code:

System.ServiceModel.EndpointAddress eaSecurity = new System.ServiceModel.EndpointAddress("https://localhost:56389/UKService.svc");
                var binding = new System.ServiceModel.BasicHttpBinding();
                binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportWithMessageCredential;
                binding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.None;
                binding.Security.Message.ClientCredentialType = System.ServiceModel.BasicHttpMessageCredentialType.UserName;


                var securityFactory = new System.ServiceModel.ChannelFactory<ServiceReference1.IUKService>(binding, eaSecurity);
                securityFactory.Credentials.UserName.UserName = "test";
                securityFactory.Credentials.UserName.Password = "test";
                myService = securityFactory.CreateChannel();

Any ideas how to solve this?

UPDATE: I look deeper in error stack and find following: System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the results of authentication. I tryed this code:

  ClientCredentials cc = securityFactory.Endpoint.Behaviors.Find<ClientCredentials>();

                cc.UserName.UserName = "test";
                cc.UserName.Password = "test";

               cc.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

But it doesn't help.

Upvotes: 0

Views: 2450

Answers (2)

Yury
Yury

Reputation: 57

I solve it this way:

System.Net.ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertValidateCallback);
 public static bool RemoteCertValidateCallback(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
        {
            return true;
        }

Upvotes: 1

CodeCaster
CodeCaster

Reputation: 151594

The problem is that your certificate is not trusted by the client. This has nothing to do with client certificates or downloading the certificate from the browser.

In order for the server certificate to be accepted by te client, you need to either:

  • Buy a certificate from a trusted certificate authority
  • Add the certificate (or its root) to the client machine's certificate store or
  • Disable certificate validation.

Upvotes: 0

Related Questions