Categories
Tips

Basic Http authentication from .NET to PHP webservice

Today, I had a major problem that had a not-so-complex-but-rather-stupid solution so I thought it might be worth sharing since I only found online solutions that were rather old.

I have remote access to a PHP webservice, written using NuSOAP. I call the methods of this webservice from a .NET application. This is no problem at all and I can easily call most webservice methods from within .NET. But some of the methods require basic authentication and now the trouble begins.

One would think that it would be enough to just set the credentials for the webservice and make sure that it authenticates on every request. Like this:

MyPhpWebservice ws = new MyPhpWebservice();
ws.PreAuthenticate = true;
CredentialCache cache = new CredentialCache();
cache.Add(
   new Uri(ws.Url),
   "Basic", 
   new NetworkCredential(wsUsername, wsPassword)
);
ws.Credentials = cache;
ws.CallSomeFunctionThatNeedsAuth();

Alas, this did not work. In many places online, people say that .NET does not actually send the authentication details on the first request for some webservice function. If this was true, the solution would simply be:

ws.CallSomeFunctionThatNeedsAuth(); // Does not auth
ws.CallSomeFunctionThatNeedsAuth(); // Should auth now?

This did not work either. Other people in other places online say that one needs to manually add the authentication details to the HttpWebRequest header. But the Visual Studio auto-created MyPhpWebservice class does not expose its WebRequest object so it cannot be directly altered. However, we can override the method GetWebRequest for the webservice and that way manually add the authentication header. This took me a while to figure out but here is a simple solution:

class MyOverriddenPhpWebservice : MyPhpWebservice
{
    protected override System.Net.WebRequest GetWebRequest(Uri uri)
    {
        HttpWebRequest request;
        request = (HttpWebRequest)base.GetWebRequest(uri);

        if (PreAuthenticate)
        {
            NetworkCredential cred =
                Credentials.GetCredential(uri, "Basic");
            if (cred != null)
            {
                byte[] credBuffer = new UTF8Encoding().GetBytes(
                    cred.UserName + ":" + cred.Password);
                request.Headers["Authorization"] =
                    "Basic " + Convert.ToBase64String(credBuffer);
            }
        }
        return request;
    }
}

The code that I wrote in Listing 1 is now perfectly valid and all I need to do is exchange MyPhpWebservice with MyOverriddenPhpWebservice.

And the best part: It works :-)

Categories
Software

Licenses continued

Well, kudos to Microsoft for their Bizspark program. It is intended to help small business by providing free Microsoft products. It’s a good way to try and get developers to start using their products. Thanks to that, I now have access to Windows and Visual Studio for free. Our intentions are still to use all open source tools by the end of our first year but for now we are forced to work in the a-bit-too-feature-rich-and-slow Visual Studio.

That’s life.