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.

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

    • Yes, certainly using Basic Authentication over SSL is much more secure. With SSL (or TLS to be more accurate) your entire session is encrypted at a lower level. So it doesn’t matter if the user name and password are plain text, because they are travelling over a secure channel.

  1. I removed all my header manipulation code because the .Add method is missing from the Headers collection, but you’re just using the indexer [].

    This could have far-reaching implications…

    Does this add or just change what’s already at the index?

    Thanks, Luke

    • Hi Luke

      No, using the indexer doesn’t change what is already in the headers collection. If you index into the collection with a key that doesn’t already exist in the collection, it will be added for you with the value you supply. If that key does already exist in the collection then the existing value will be over written with the value you supply. Any existing headers in the collection will remain unchanged.

      You can also change the User Agent header with the same technique, so

      request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + credentials;
      request.Headers[System.Net.HttpRequestHeader.UserAgent] = "MyApp 1.0";

      would yield the headers:

      Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
      User-Agent: MyApp 1.0

      if you added second User Agent header it would overwrite the first. So:

      request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + credentials;
      request.Headers[System.Net.HttpRequestHeader.UserAgent] = "MyApp 1.0";
      request.Headers[System.Net.HttpRequestHeader.UserAgent] = "MyApp 2.0";

      would yield the headers:

      Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
      User-Agent: MyApp 2.0

      A

  2. Bobby – I’m also having a nightmare. The phone isn’t reattaching the cookie it gets from the AuthenticationService to subsequent calls to services at the same domain.

    My blood is boiling. Microsoft continually leave out some tiny thing that wastes so much of my time and flies in the face of their guidance on how to architect a full system on their technology stack.

  3. As I type I’m on the phone to Microsoft about this problem. I copied and pasted my code over from the full framework and as soon as I saw the Add method had been removed, I thought that was a deliberate act to prevent coding changes to the headers.

    Thanks very much for this.

    Luke

  4. Hi, I’m also frustrated because we cannot get it to work to use WCF with SSL and Basic Authentication. I’ve to implement my own wrappers for all Webservices with the HttpWebRequest object, add the authorization and parse the response with the ugly XDocument. Things which worked since .NET CF 2.0.

  5. Pingback: Windows Phone 7 Developer Roundup #5 for 12/08/2010 « "A" Developer`s Life

    • No, but I would guess we should probably expect one next month (or February at the latest). I must say Microsoft is seriously in danger of losing momentum if they don’t start moving quicker than they are.

  6. That’s extactly what I want to do. Could you give me some details about the Client- and ServerConfiguration File, please.
    I would like to use HTTPS (transport) and BasicAuthentication. Only HTTPS works like a charm but both combinated doesn’t work for me.
    My current ServerConfigFile:

    And my Client Config:

    Thank you.

  7. Thank you for this one Adam.. have the same problem like Jason.. Could you please help me?

    Seems my web.config (WCF) to be right?

    Thank you in advance. Greg

  8. Pingback: Call SOAP Web Service With Basic Authorization | Road to Data Professional

Leave a reply to Luke Puplett Cancel reply