Cook Computing

PreAuthenticate Property of WebRequest - Solution

January 29, 2009 Written by Charles Cook

The previous post explained that using the PreAuthenticate property of System.Net.WebRequest does not prevent two round-trips when making the first request for an HTTP resource protected by Basic Authentication. The workaround for this is to generate and set the HTTP Authorization header explicitly like this:


  static string CreateAuthorization(string realm,
    string userName, string password)
  {
    string auth = ((realm != null) && (realm.Length > 0) ?
    realm + @"\" : "") + userName + ":" + password;
    auth = Convert.ToBase64String(Encoding.Default.GetBytes(auth));
    return auth;
  }

The return value from this function can be used to set the Authorization header:


    WebRequest req = WebRequest.Create(uri);
    string auth = CreateAuthorization("cookcomputing.com", "user",
      "password");
    req.Headers["Authorization"] = "Basic " + auth;

This will result in a single round-trip for each request:

  • Client: GET /foo/foo.html HTTP/1.1
    Authorization: Basic c3RvY2tsZXkuYXZheWEuY29tXGNoY29vazpBcmVuaWcxNjAh
  • Server: HTTP/1.1 200 OK
  • Client: GET /foo/bar.html HTTP/1.1
    Authorization: Basic c3RvY2tsZXkuYXZheWEuY29tXGNoY29vazpBcmVuaWcxNjAh
  • Server: HTTP/1.1 200 OK

The same technique can be used with XML-RPC.NET, for example:


using System;
using System.Text;
using CookComputing.XmlRpc;

[XmlRpcUrl("http://localhost:81/xmlrpc/RPC2.ashx")]
public interface IStateName : IXmlRpcProxy
{
  [XmlRpcMethod("examples.getStateName")]
  string GetStateName(int stateNumber);
}

class Program
{
  static string CreateAuthorization(string realm, 
    string userName, string password)
  {
    string auth = ((realm != null) && (realm.Length > 0) ?
    realm + @"\" : "") + userName + ":" + password;
    auth = Convert.ToBase64String(Encoding.Default.GetBytes(auth));
    return auth;
  }

  static void Main(string[] args)
  {
    IStateName proxy = XmlRpcProxyGen.Create<IStateName>();
    string auth = CreateAuthorization("cookcomputing.com", "user", "password");
    proxy.Headers["Authorization"] = "Basic " + auth;
    string ret = proxy.GetStateName(1);
  }
}