Search code examples
c#wcffiddlerbasic-authentication

Basic Authentication appears to have no security header


I have written a very simple WFCSerice that returns the Windows username supplied. Here is the client side code:

public Form1()
        {
            ServiceReference1.Service1Client s1 = new ServiceReference1.Service1Client();
            s1.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
            string str = s1.ReturnWindowsUsername();
            InitializeComponent();
        }

I can see the credentials in the HTTP Header using Fidddler:

enter image description here

I have tried to do the same thing with Basic Authentication (accessing another web service that supports Basic Authentication). Here is the client side code:

public Form1()
        {
            InitializeComponent();
            ServiceReference1.Service1Client s1 = new ServiceReference1.Service1Client();
            s1.ClientCredentials.UserName.UserName = "testuser";
            s1.ClientCredentials.UserName.Password = "testpassword";
            string str = s1.GetData(1);

        }

Here is the screenshot from Fiddler when using Basic Authentication:

enter image description here

Why is there nothing in the header when using Basic Authentication. The Basic Authentication service seems to work as expected. Here is the response (interestingly there appear to be two requests and two responses):

enter image description here


Solution

  • Basic authentication works on the HTTP level. The general flow is that the client requests a resource, then the server issues a challenge, then the client issues a new request with an Authorization header included. If the username and password in the Authorization header are accepted by the server, the client will usually then add the header for subsequent request without going through the request - challenge - re-request-with-authorization steps again.

    If you have everything setup correctly, you should expect to see two requests in Fiddler.

    1. One request with no Authorization header included. The response from the server for this request will be a 401 with a WWW-Authenticate: Basic realm="your realm" header attached.
    2. Then you should see a second request where an Authorization header has been sent from the client.

    Here is a sample from my environment:

    enter image description here

    If you don't see the 401 challenge from the server, then basic authentication is not correctly set up.

    In order for the service proxy to supply the header, you need to configure your client binding to use <transport clientCredentialType="Basic"/>. Or that's what I did, who knows with WCF with it's myriad of configuration options.

    EDIT: I used this on the service side:

    <bindings>
      <basicHttpBinding>
        <binding name="httpTransportCredentialOnlyBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    

    On the client:

    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService1">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:53156/Service1.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IService1" contract="WcfTest_CBT.IService1"
        name="BasicHttpBinding_IService1" />
    </client>
    

    I use basicHttpBinding, TransportCredentialOnly and Basic in order to test this easily without SSL hassle etc.