How to use a Service Reference with a basic authentication WCF SOAP Service

Stephen Nutt picture Stephen Nutt · Mar 22, 2012 · Viewed 11.2k times · Source

I have a WCF SOAP service that uses basic access authentication. SSL is not being used - I understand the security issues here.

Using the WCFTestClient application I have verified the service works by temporarily hard coding into the service a user name and password to use when the Authorization header is not present.

I am now trying to write a test application that passes the credentials via the Authorization header. I've added a service reference to my service in my test app but the Authorization header is not present in the http request. The generated MyServiceClient class uses System.ServiceModel.ClientBase

In my test app I am setting the credentials as follows

MyServiceClient client = new MyServiceClient("BasicHttpBinding_MyService");
client.ClientCredentials.UserName.UserName = "WebServiceUsername";
client.ClientCredentials.UserName.Password = "WebServicepassword";

I have also tried as follows

MyServiceClient client = new MyServiceClient();
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "WebServiceUsername";
loginCredentials.UserName.Password = "WebServicepassword";
client.Endpoint.Behaviors.Remove(client.Endpoint.Behaviors.Find<ClientCredentials>()); 
client.Endpoint.Behaviors.Add(loginCredentials);

The service web.config is as follows

<services>
  <service name="MyService" behaviorConfiguration="MyBehavior" >
    <endpoint contract="MyService" binding="basicHttpBinding" />
    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
  </service>
</services>

The test app.config is as follows

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_MyService">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:55314/MyService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_MyService"
        contract="MyService" name="BasicHttpBinding_MyService" />
    </client>
  </system.serviceModel>
</configuration>

Any thoughts on what I am missing?

Answer

bobek picture bobek · Mar 22, 2012

This is a good starting point, move your binding and endpoint info from config file to your class:

        protected BasicHttpBinding binding = new BasicHttpBinding()
        {
            Name = "Name your binding here",
            CloseTimeout = new TimeSpan(0, 1, 0),
            OpenTimeout = new TimeSpan(0, 1, 0),
            ReceiveTimeout = new TimeSpan(0, 10, 0),
            SendTimeout = new TimeSpan(0, 1, 0),
            AllowCookies = false,
            BypassProxyOnLocal = false,
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
            MaxBufferSize = 65536,
            MaxBufferPoolSize = 524288,
            MaxReceivedMessageSize = 65536,
            MessageEncoding = WSMessageEncoding.Text,
            TransferMode = TransferMode.Buffered,
            UseDefaultWebProxy = true,
            Security = new BasicHttpSecurity()
            {
            Mode = BasicHttpSecurityMode.Transport,
            Message = new BasicHttpMessageSecurity() { AlgorithmSuite = SecurityAlgorithmSuite.Default, ClientCredentialType = BasicHttpMessageCredentialType.UserName}, 
            Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Digest }
            },
        };
        protected EndpointAddress endPoint = new EndpointAddress("http://localhost:55314/MyService.svc");

and then

MyServiceClient client = new MyServiceClient(binding, endpont);

Try this, and tweak the binding into your needs, especially "Security".