Calling Office365 API from a Windows Phone 8.1 App

Did you install the preview of Windows Phone 8.1? I sure did, and it’s awesome!

Windows Phone 8.1 introduces a great new feature, which was until recently only available on Windows 8.x: the WebAuthenticationBroker (WAB for short from now on). ADAL for Windows Store leverages the WAB for all of its authentication UI rendering needs, and that saved us a tremendous amount of work in respect to other platforms (such as classic .NET) on which we had to handle the UX (dialog, HTML rendering, navigation, etc) on our own.

To give you a practical example of that, and to amuse myself during this 9.5 hours Seattle-Paris flight I am sitting on, I am going to show you how to use the WAB on Windows Phone 8.1 to obtain a token from Azure Active Directory: you’ll see that the savings in respect to the older Windows Phone sample (where I did have to handle the UX myself) are significant. If you prefer to watch a video, rather than putting up with my logorrhea, check out the recording of the session on native clients I delivered at //BUILD just 10 days ago: the very first demo I show is precisely the same app, though I cleaned up the code a bit since then.

The WebAuthenticationBroker and the Continuation Pattern

The WAB on Windows Phone 8.1 differs from its older Windows 8.x sibling in more than the size of its rendering surface. The one difference you can’t ignore (and the reason for which you can’t just reuse ADAL for Windows Store on the phone) lies in the programming model it exposes. Note: the WAB coverage on MSDN is excellent, and I recommend you refer to it rather than relying on what I write here (usual disclaimers apply). Here I’ll just give a barebone explanation covering the essential for getting the WAB to work with AAD.

image

Referring to the diagram above. The idea is that (1) whenever you call the phone WAB from your code, your app gets suspended and the WAB “app” takes over the foreground spot. The user goes through (2) whatever experience the identity provider serves; once the authentication flow comes to an end, (3) the WAB returns control to your app and disappears.
Here that’s where things get interesting. For your app, this is just another activation: you need to add some logic to detect that this activation was caused by the WAB returning from an authentication, and ensure that the values returned by the WAB are routed to the code that needs to resume the authentication logic and process them.
The idea is that you need in your app an object which implements a well-known interface (IWebAuthenticationContinuable), which includes a method (ContinueWebAuthentication) meant to be used as the re-entry point at reactivation time. In the diagram above it is the page itself that implements IWebAuthenticationContinuable; the OnActivated handler (4) calls the method directly, passing the activation event arguments which will be materialized in ContinueWebAuthentication as WebAuthenticationBrokenContinuationArgs. Those arguments will contain the values you typically expect from the WAB, such as the authorization code produced by an OAuth code grant flow.

This is a common pattern in Windows Phone 8.1: it goes under the name “AndContinue”, from the structure of the primitives used. It is applied whenever a “system” operation (such as the WAB, but also file picking) might end up requiring a lot of resources, making it hard for an app on a low power device to keep active in memory both the app and the process handling the requested task. Once again, MSDN provides great coverage for this.

The Sample

Too abstract for your taste? Presto, let’s look at some code. Here I will skip all of the client app provisioning in AAD, as we’ve covered that task many times. If you want a refresher, just head to one of the samples on GitHub and refer to the instructions there. <LINK>

As mentioned in the title, we want an app that will invoke an Office365 API. We won’t do anything fancy with the results, as I just want to show you how to obtain and use a suitable token. If you want to get a trial of Office 365, check out this link <LINK>. Also, if you don’t want to set up a subscription you can easily repurpose this sample to call any other API (such as the Graph or your own).

Ready? Go! Create a new blank Windows Phone 8.1 app. Make sure to pick up the store flavor. Add a button for triggering the API call.

In your main page, add the declaration for your IWebAuthenticationContinuable. Note that you can decide to return a value, if you so choose.

 interface IWebAuthenticationContinuable
{
   void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args);
}

 

That done, add it to the page declaration as an implemented interface, and add the logic for requesting tokens and using them via the continuation model. We’ll flesh those stubs out in a moment.

public sealed partial class MainPage : Page, IWebAuthenticationContinuable
{

  //...

   private void btnInvoke_Click(object sender, RoutedEventArgs e)
   {
       RequestCode();          
   }

   public async void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
   {
       string access_token = await RequestToken(args.WebAuthenticationResult);
       HttpClient httpClient = new HttpClient();
       httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);
       HttpResponseMessage response = httpClient.GetAsync("https://outlook.office365.com/EWS/OData/Me/Inbox/Messages?$filter=HasAttachments eq true&$select=Subject,Sender,DateTimeReceived").Result
       if (response.IsSuccessStatusCode)
       {
         ShowMessage(response.Content.ReadAsStringAsync().Result);
       }
   }
//...

 

The btnInvoke_Click triggers the request for a token, via the call to the yet-to-be-defined method RequestCode(). We know that requesting a code will require user interaction, hence we can expect that the call to AuthenticateAndContinue (hence the app deactivation & switch to the WAB) will take place in there. That explains why there’s nothing else after the call to RequestCode.

The ContinueWebAuthentication method implements the logic we want to run once the execution comes back from the WAB. The first line, calling the yet-to-be-defined RequestToken, takes the results from the WAB and presumably uses it to hit the Token endpoint of the AAD’s authorization server.

The rest of the method is the usual boilerplate logic for calling a REST API protected by the OAuth2 bearer token flow – still, I cannot help but marvel at the amazing simplicity with which you can now access Office resources. With that simple (and perfectly readable!) string I can obtain a list of al the messages with attachments from my inbox, and even narrow down to which fields I care about Smile

Let’s take a look at the code of RequestCode and RequestToken.

 string Authority = "https://login.windows.net/developertenant.onmicrosoft.com";
 string Resource = "https://outlook.office365.com/";
 string ClientID = "43ba3c74-34e2-4dde-9a6a-2671b53c181c";
 string RedirectUri = "http://l";

  private void RequestCode()
     {            
         string authURL = string.Format(
             "{0}/oauth2/authorize?response_type=code&resource={1}&client_id={2}&redirect_uri={3}",
             Authority,
             Resource,
             ClientID,
             RedirectUri);            
         WebAuthenticationBroker.AuthenticateAndContinue(new Uri(authURL), new Uri(RedirectUri), null, WebAuthenticationOptions.None);
     }

     private async Task<string> RequestToken(WebAuthenticationResult rez)
     {
         if (rez.ResponseStatus == WebAuthenticationStatus.Success)
         {
             string code = ParseCode(rez.ResponseData);
             HttpClient client = new HttpClient();
             HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, string.Format("{0}/oauth2/token", Authority));
             string tokenreq = string.Format(
                     "grant_type=authorization_code&code={0}&client_id={1}&redirect_uri={2}",
                     code,ClientID,Uri.EscapeDataString(RedirectUri));
             request.Content = new StringContent(tokenreq, Encoding.UTF8, "application/x-www-form-urlencoded");

             HttpResponseMessage response = await client.SendAsync(request);
             string responseString = await response.Content.ReadAsStringAsync();

             var jResult = JObject.Parse(responseString);
             return (string)jResult["access_token"];
         }
         else
         {   
             throw new Exception(String.Format("Something went wrong: {0}",rez.ResponseErrorDetail.ToString()));
         }            
     }

     private string ParseCode(string result)
     {
         int codeIndex = result.IndexOf("code=", 0) + 5;
         int endCodeIndex = result.IndexOf("&", codeIndex);
         // Return the access code as a string
         return result.Substring(codeIndex, endCodeIndex - codeIndex);
     }

 

This is mostly protocol mechanics, not unlike the equivalent logic in the older Windows Phone samples I discussed on these pages.

RequestCode crafts the request URL for the Authorization endpoint and passes it to the WAB, calling AuthenticateAndContinue. By now you know what will happen; the app will go to sleep, and the WAB will show up – initialized with the data passed here. MUCH simpler than having to create an in-app auth page and handling navigation by yourself.

RequestToken and its associated utility function ParseCode retrieve the authorization code from the response data returned by the WAB, construct the request for the Token endpoint, hits it, and parses (via JSON.NET, finally available for Windows Phone 8.1! Smile for my //BUILD demo I had to use the data contract serializer, bleah) the access token out from AAD’s response.

If you paid attention to the explanation to how the WAB continuation pattern works, you know that there’s still something missing: the dispatching logic that upon (re)activation routes the WAB results to ContinueWebAuthentication. Open the App.xaml.cs file, locate the OnActivated handler and add the following.

protected async override void OnActivated(IActivatedEventArgs e)
{
    var rootFrame = Window.Current.Content as Frame;

    var wabPage = rootFrame.Content as IWebAuthenticationContinuable;
    if (wabPage != null)
    {
         wabPage.ContinueWebAuthentication(e as WebAuthenticationBrokerContinuationEventArgs);
    }

    Window.Current.Activate();
}

Now, I know that my friends in the Windows Phone 8.1 team will frown super-hard at the above. For starters: to do things properly, you should be prepared to be reactivated by multiple *AndContinue. In general, the documentation provides nice classes (like the ContinuationManager) you can use to handle those flows with more maintainable code than the hack I have put together here. My goal here (and during the //BUILD session) was to clarify the new WAB behavior with the least amount of code. Once that is clear to you, I encourage you to revisit the above and re-implement it using the proper continuation practices.

Aaanyway, just to put a bow on this: here there’s what you see when running the app. I landed in Paris and I can finally connect to the cloud Smile

The first page:

1

Pressing the button triggers RequestCode, which in turns calls WebAuthenticationBroker.AuthenticateAndContinue and causes the switch to the WAB:

2

Upon successful auth, we get back a token and we successfully call Exchange online:

3

Ta-dah! Note

Wrap

Windows Phone 8.1 is a great platform, and WAB is a wonderful addition that will make us identity people very happy. The continuation model will indeed impose a rearranging of the app flow. We are looking at ways in which we can abstract away some of the details for you, so that you can keep operating with the high level primitives you enjoy in ADAL without (too much) abstraction leakage. Stay tuned!

Leave a Reply

Your email address will not be published. Required fields are marked *