How to implement Basic HTTP Authentication in WCF on Windows Phone 7

Unfortunately the version 1.0 of the Windows Phone 7 SDK is missing a few essentials.  One of which is that the Phone’s WCF implementation doesn’t support basic authentication for non-WCF services. So if you need to supply a user name and password to access a remote service, you’re on your own.  Setting the Security mode in your binding config as you normally would doesn’t work.

Fortunately basic HTTP authentication is easy enough to implement yourself.

As the name suggests Basic Authentication is basic.  It is simply an “Authorization” header which is added to the HTTP call which contains the base64 encoded user name and password.

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

The good news is that implementing basic authentication means simply adding this header to your going calls.  Here’s how.

Firstly we need a method to encode the credentials:

private string EncodeBasicAuthenticationCredentials(string username, string password)
{
  //first concatenate the user name and password, separated with :
  string credentials = username + ":" + password;

  //Http uses ascii character encoding, WP7 doesn’t include
  // support for ascii encoding but it is easy enough to convert
  // since the first 128 characters of unicode are equivalent to ascii.
  // Any characters over 128 can’t be expressed in ascii so are replaced
  // by ?
  var asciiCredentials = (from c in credentials
                     select c <= 0x7f ? (byte)c : (byte)'?').ToArray();

  //finally Base64 encode the result
  return Convert.ToBase64String(asciiCredentials);
}

Now that we have a means of encoding our credentials we just need to add them to the headers of our WCF request.  We can easily do this by wrapping the call in an OperationContextScope:

var credentials = EncodeBasicAuthenticationCredentials("username", "password");

using (OperationContextScope scope =
          new OperationContextScope(service.InnerChannel))
{
  HttpRequestMessageProperty request = new HttpRequestMessageProperty();
  request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + credentials;

  OperationContext.Current.OutgoingMessageProperties.Add(
                                     HttpRequestMessageProperty.Name, request);

  service.DoSomethingAsync();
}

This easily adds basic HTTP authentication for your WCF call on the fly.  Unfortunately using the OperationContext like this means you have to remember to add the header each time you make a call. If you are going to regularly be needing to do this you might want to consider creating a custom Channel, which automatically adds the header to all outgoing requests.  The technique would essentially be the same, it’s just that it would code it once for the channel rather than for each individual call. [Update 08/12/2010: There is no centralised way to do this in Silverlight 3.0]

Also it is always worth mentioning that basic authentication is not secure.  Encoding the username and password does not encrypt them.  They are transmitted over the internet in the clear for anyone to read.