Accessing a Service on the Windows Azure Service Bus from Windows Phone 7

Recently I was working on putting together a sample of how to use the service relay feature of the Windows Azure Service Bus.  By using the Windows Azure Service Bus as a service relay, it is possible to expose on-premises services in a secure way, without the need to punch holes in your firewall or stand up a lot of new infrastructure.  Part of the sample included accessing the service from Windows Phone 7.  Easy enough, right?

Setting up the server side to register on the Service Bus is fairly straightforward.  There are several good examples online, the Azure AppFabric SDK, and the Windows Azure Platform Training Kit.  So, I’m not going to go into much detail here on that.  However, I do want to be sure to point out that services can have one of two types of client authentication – none and an access token.  Obviously, not requiring a token is a lot easier – just call the service like any other WCF REST service.  Adding a security token ups the complexity a little.  By requiring an access token a client would need to authenticate with Windows Azure Access Control Services first, and then provide the token as part of the service call.  An area that can be confusing when dealing with authentication in this situation is the Service Bus still uses ACS v1 for authentication, not the newer, cooler, ACS v2.  You will see in the Windows Azure Management Portal that the Service Bus is set to use ACS V1, but when you look at Access Control in the portal, you’ll just see your ACS V2 namespace.

The client security requirement is configured in the server side .config file.

<bindings> 
 <webHttpRelayBinding> 
 <binding name=""> 
 <!--<security relayClientAuthenticationType="None"  mode="Transport"/>--> 
<security relayClientAuthenticationType="RelayAccessToken"  
mode="Transport"/> 
 </binding> 
 </webHttpRelayBinding> 
</bindings>

Now that I had the server side set up, it was time to work on the WP7 side of the sample.  As I mentioned before, there are a lot of samples available for setting up both the service and client side of a Service Bus connection. What there was not (at least that I could find) was examples of setting up a client to authenticate with ACS, without using assemblies from the Azure AppFabric SDK such as Microsoft.ServiceBus.dll.  Adding to the “fun” was that all web calls on Windows Phone 7 must be done asynchronously – meaning the System.Net.WebClient behaves a little differently on WP7 than it does on a desktop or server app.  So, that said, let’s get on with it! 

There are two things that are needed – authentication with ACS and sending the ACS provided token to the service.  Let’s start with authenticating the client with ACS.  For my sample I decided to go with what is the most basic form of authentication, a shared secret.  This will involve creating a WRAP message, sending it to ACS, and then extracting the ACS token from the response.

private void GetDataUsingAcsSecurity()
{
 var webClient = new WebClient();             
 string acsUri = 
@https://mynamespace-sb.accesscontrol.windows.net/WRAPv0.9/;                          
 
string data = 
 string.Format("wrap_name={0}&wrap_password={1}&wrap_scope={2}",                 
 HttpUtility.UrlEncode("owner"),                  
 HttpUtility.UrlEncode("iALK8XkWQb89G5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
 HttpUtility.UrlEncode(http://mynamespace.servicebus.windows.net));

 webClient.Headers["Content-Type"] = 
 "application/x-www-form-urlencoded";             

 webClient.UploadStringCompleted += webClient_UploadStringCompleted;
 webClient.UploadStringAsync(new Uri(acsUri), "POST", data);         
}

There are a few things to point out about this code.  Now, maybe it’s because I haven’t written a lot of C# code to access a REST service, some of the code to make this work were not obvious to me.   First, you must set the “Content-Type” HTTP header.  Second, you’ll want to use the STS Endpoint that is listed in the Windows Azure Management Portal.

STS Endpoint

So, now we need the code to handle the response.  That code will need to extract the ACS token from the response and pass it on to the service.

void webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
string token = 
e.Result .Split('&').Single(x => x.StartsWith("wrap_access_token=",
StringComparison.OrdinalIgnoreCase)).Split('=')[1];
string decodedToken = HttpUtility.UrlDecode(token); 

var uriBuilder = 
new UriBuilder(https://mynamespace.servicebus.windows.net/claims);

uriBuilder.Path += 
string.Format("/claim/{0}/amount", PolicyIdBox.Text); 

var webClient = new WebClient(); 
webClient.Headers["Authorization"] = 
string.Format("WRAP access_token=\"{0}\"", decodedToken);

webClient.DownloadStringCompleted += 
(s, args) => ParseAndShowResult(args);

webClient.DownloadStringAsync(uriBuilder.Uri);
}

The key, at least for me, was the line which decodes the token received from ACS.  Note – ParseAndShowResult() is simply a helper method to parse the result of the service call and show on the phone, so nothing exciting going on there.

In the end, this wasn’t all that bad.  The problems for me were really related to a lack of understanding of what was needed with regards to authenticating with ACS and likely a little inexperience in working with REST services.  Hopefully this quick sample will save someone else from some frustrating 2:00 AM coding sessions.

3 thoughts on “Accessing a Service on the Windows Azure Service Bus from Windows Phone 7

  1. This blog is helpful to get the token without using servicebus.dll. It would be great if you could please provide the next steps to access the on-premise service from the Windows phone

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.