Technical Note: Windows Phone 7: Basic Authentication over HTTPS.

A note directly related to the larger blog project started with the last post, https://blogs.msdn.com/b/ralph.squillace/archive/2011/01/03/cloud-data-a-newbie-series-the-issues.aspx. While I have been working on a lot of phone applications, almost all of the work around the net using HTTP web requests involves Web services -- REST or SOAP style -- that do not require much if anything in the way of authentication and security. Yet when a service provides data of reasonable value, that's what you need. Currently the Windows Phone 7 supports only HTTPS to secure communications, but since that's what is used by the bulk of the Internet selling music, books, tickets, and so on, it is more than sufficient for the vast majority of consumer applications. This post is to demonstrate how to make those calls on the Windows Phone 7 using Basic Authentication over HTTPS using several different mechanisms. Each of these works against an HTTPS endpoint at the Windows Azure DataMarket to access free data sources, such as the United States crime statistics from 2008.

ASIDE: Some people have noticed that the WCF implementation on the phone does not support "easy" Basic authentication of HTTP. No, it doesn't. But that's by design to protect you from "accidentally" using passwords in the clear over the network. Perhaps that's too much "protecting you", but it is documented here, in the note in the topic. If you don't use HTTPS -- that is, if you use HTTP -- the Client.Credentials property is ignored by design.

SECURITY NOTE: Because whenever sample code does not mention this, there's always some people in a big hurry that you have to remind: Obtain the username/password in a secure fashion. The most reasonably secure fashion is to prompt for it so that the user can enter it in a PasswordBox. However, there are other ways to encrypt in a strong way the strorage of such data on the phone. More in the future about several ways, but one is described here by Rob Tiffany: Don’t forget to Encrypt your Windows Phone 7 Data.

Using the WebClient Class (a good example with slightly different style found here!)

Using System.Net;

WebClient client = new WebClient();

// Handle the response when it comes.
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);

// Your password; some services will call this a key, or a secret, or something.
string accountkeyOrPassword = "<account or key or password goes here>";

// Add the username/accountkeyOrPassword to the Client.Credentials property by creating a new NetworkCredential
client.Credentials = new NetworkCredential("accountKey", accountkeyOrPassword);

// Handle the response
client.DownloadStringAsync(new Uri("https://api.datamarket.azure.com/Data.ashx/data.gov/Crimes/CityCrime?$filter=City%20eq%20%27Seattle%27&$top=100"));

Using the HttpWebRequest Class

HttpWebRequest client
= WebRequest.CreateHttp(
new Uri("https://api.datamarket.azure.com/Data.ashx/data.gov/Crimes/CityCrime?$filter=City%20eq%20%27Seattle%27&$top=100")
) as HttpWebRequest;

// Your password; some services will call this a key, or a secret, or something.
string accountkeyOrPassword = "<account or key or password goes here>";

// Add the username/accountkeyOrPassword to the Client.Credentials property by creating a new NetworkCredential
client.Credentials = new NetworkCredential("accountKey", accountkeyOrPassword);

// To support Windows Azure DataMarket
client.AllowReadStreamBuffering = true;

// Call and handle the response.
client.BeginGetResponse(
(asResult) =>
{
Dispatcher.BeginInvoke(
() =>
{
try
{
var response = client.EndGetResponse(asResult);
System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
responseString = reader.ReadToEnd();
}
catch (WebException failure)
{
throw failure;
}
});
},
null
);

In a next post, I'll show how to use several different optimized client libraries to do this work.