1
votes

I'm trying to implement a custom WS binding with compression and message security with ClientCredentialType set to 'None'. The service is configured and running successfully. I've also managed to configure the client and run it successfully. However, I need to set-up the client programatically, so when I try to translate the client configuration into code, I get the error 'The service certificate is not provided for target 'xxx'. Specify a service certificate in ClientCredentials.' I'm using the auto-generated proxy client, and I've followed recommendations to override the client constructor and specify the service certificate CertificateValidationMode directly on the ClientCredentials or in the client endpoint behaviors, but still no luck.

I would appreciate any help in resolving this. For reference, I include below the configuration and its code translation.

Client configuration:

<system.serviceModel>
 <bindings>
  <customBinding>
    <binding name="customWSBinding" sendTimeout="00:15:00">
      <security authenticationMode="SecureConversation" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
        <secureConversationBootstrap authenticationMode="AnonymousForSslNegotiated" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" />
      </security>
      <gzipMessageEncoding innerMessageEncoding="textMessageEncoding"/>
      <httpTransport hostNameComparisonMode="StrongWildcard" manualAddressing="False"
                      maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
                      authenticationScheme="Anonymous" bypassProxyOnLocal="False" realm="" useDefaultWebProxy="True"/>
    </binding>
  </customBinding>
 </bindings>
 <client>
  <endpoint address=""
    binding="customBinding"
    bindingConfiguration="customWSBinding"
    behaviorConfiguration="ClientBehavior"
    contract="IService"
    name="ServiceEndpoint">
    <identity>
      <dns value="contoso.com"/>
    </identity>
  </endpoint>
 </client>
 <behaviors>
  <endpointBehaviors>
    <behavior name="ClientBehavior">
      <clientCredentials>
        <serviceCertificate>
          <authentication certificateValidationMode="None"/>
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
 </behaviors>
</system.serviceModel>

The equivalent code:

SecurityBindingElement securityElement =   SecurityBindingElement.CreateSecureConversationBindingElement(SecurityBindingElement.CreateAnonymousForCertificateBindingElement());
securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

GZipMessageEncodingBindingElement encodingElement = new GZipMessageEncodingBindingElement();
TextMessageEncodingBindingElement txtMsgBE = new TextMessageEncodingBindingElement();
encodingElement.InnerMessageEncodingBindingElement = txtMsgBE;

HttpTransportBindingElement httpTransportElement = new HttpTransportBindingElement();
httpTransportElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
httpTransportElement.ManualAddressing = false;
httpTransportElement.MaxReceivedMessageSize = Int32.MaxValue;
httpTransportElement.MaxBufferSize = Int32.MaxValue;
httpTransportElement.MaxBufferPoolSize = Int32.MaxValue;
httpTransportElement.AuthenticationScheme = AuthenticationSchemes.Anonymous;
httpTransportElement.BypassProxyOnLocal = false;
httpTransportElement.UseDefaultWebProxy = true;

System.ServiceModel.Channels.Binding binding = new CustomBinding(securityElement, encodingElement, httpTransportElement);
binding.SendTimeout = TimeSpan.FromMinutes(15);

EndpointAddress address = new EndpointAddress(new Uri(svcURL),    EndpointIdentity.CreateDnsIdentity("contoso.com"));

ServiceClient svcClient = new ServiceClient(binding, address);

The overridden proxy client:

public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
:base (binding, remoteAddress)
{
    System.ServiceModel.Description.ClientCredentials cc = new System.ServiceModel.Description.ClientCredentials();
    cc.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;

    base.Endpoint.Behaviors.RemoveAt(1);
    base.Endpoint.Behaviors.Add(cc);
}
1

1 Answers

0
votes

CreateAnonymousForCertificateBindingElement() method provides binding element for anonymous client-authentication and certificate based service authentication. Hence if is asking for a service certificate.