January 2013

Volume 28 Number 01

Security - Access Online Services with the Windows Runtime and OAuth

By Tim Kulp | January 2013

Once upon a time, back in the Web 1.0 days, Web sites were silos of content to be read and nothing more. As Web 2.0 buzzed into development shops, Web sites became online services with APIs used by developers to mix and match components, data and functionality. Now, mashups allow developers to access rich content libraries without the overhead of housing the data in their server rooms.

With the Windows Runtime (WinRT), you can bring the power of mashups to your next Windows Store app. Whether you’re managing data with XmlHttpRequest (XHR) or authenticating to a remote service with the WebAuthenticationBroker class, Windows Library for JavaScript (WinJS) and the Windows Runtime make mashing online services with your app easy.

Contoso Photo Finish

In this article I’m going to build a mashup called Contoso Photo Finish. It lets runners track their miles and post a picture from their runs. Many runners like to share information such as distance and location of their runs on social networks. Contoso Photo Finish lets users tell their friends about their runs with comments and pictures on Facebook. This app will connect to two different services:

  • Windows SkyDrive to retrieve a picture from the run
  • Facebook to post the picture for their friends to view

Contoso Photo Finish will combine these services to provide a connected experience for the user. This article assumes you have Visual Studio 2012 open with the JavaScript | Windows Store | Blank App template ready for you to start coding.

Mashup Hurdles: Authorization and Authentication

If an app (Web or Windows Store) wants to post content to Facebook, the first hurdle to overcome is authentication. Facebook needs to know who’s connecting to it. When users try to log in to apps, they claim an identity (usually in the form of a username) and a credential (such as a password, security token, biometric device and so on) to prove they should have access to the requested identity. Authentication is the process of validating a user’s identity through a credential.

After authenticating the user, the mashup has another challenge: determining what the user can do in the system. Authorization is the process of permitting or denying actions an identity is attempting to perform based on some attribute or security role membership. As an example, in Twitter my identity is not permitted to delete all the tweets of all users. I’m not authorized to perform that action because I’m not a member of the security role with permission to do that. Together, authentication and authorization (A&A) represent the question: User, who are you and what can you do?

Mashups amplify these challenges because the developer building the mashup doesn’t have access to where the identities, credentials and security roles are stored (often referred to as a credential store). So if I can’t verify who’s who and what they can do, how can I build a mashup for apps such as Facebook? OAuth to the rescue!

OAuth: Accessing Resources, Not Apps

OAuth addresses the challenge of A&A for mashups. Imagine App X wants to access content from Online Service Y. Instead of the user authenticating to App X, the user authenticates to Online Service Y because the user’s credentials are stored in Online Service Y’s credential store. The user then permits App X to access specified resources from Online Service Y for a limited time. Permission to access Online Service Y resources is returned to App X as an access token (sometimes referred to as just a “token”).

In traditional Web A&A models, two participants work together to determine a user’s access: the app and the user (or the server and client). In OAuth a third participant is introduced: the resource server. Resource servers are the third parties who have a resource (such as a photo) stored on the server that a client needs to access. In Contoso Photo Finish, Facebook is a resource server. The resource that Contoso Photo Finish wants to access is the user’s status, in order to post a message.

OAuth Clients and Their Authentication Processes

There are two types of clients in OAuth, and which type to use is decided by the client’s level of trust. Confidential clients can keep their credentials secure and are meant for highly trusted environments. Examples of confidential clients are server-side Web apps where the client secret can be maintained in a controlled, secure environment. Confidential clients use the Authorization Code process to obtain a security token by providing the client secret to the resource server as a means of authenticating the client.

Public clients can’t keep their credentials secure because they run in a hostile environment. Example public clients would be user-agent apps (that is, JavaScript Web apps) or native apps (such as Windows Store apps). Public clients use the “implicit grant” process to obtain a security token because the client secret can’t be stored in a secure manner within a hostile environment that’s outside the developer’s control.

Windows Store apps can be configured to use either implicit grant or authorization code processes for OAuth (you can read more about implicit grant and authorization code processes at bit.ly/yQjyQZ). It’s a security best practice to use implicit grant any time an app is out of the developer’s control.

In Figure 1 I examine an implicit grant process where the client starts the conversation by attempting to determine a user’s identity with the resource server.

Windows Store App Implicit Grant Conversation
Figure 1 Windows Store App Implicit Grant Conversation

The steps illustrated in Figure 1 are explained here:

  1. The Windows Store app needs to perform some functionality that requires access to the Facebook API.
  2. The user connects to the resource server through a URI that includes information about the Windows Store app trying to access the Facebook API. This is usually in the form of an app ID or client ID code. The user provides a username and password to log in to Facebook.
  3. Assuming successful login, Facebook provides the Windows Store app with an access token.
  4. The Windows Store app can now provide the user with data from the Facebook API using the access token provided by Facebook to get the user’s feed, post pictures and so on.

Making this conversation happen is surprisingly easy through the new Windows.Security.Authentication.Web namespace.

WebAuthenticationBroker

In Windows Store apps the WebAuthenticationBroker class (bit.ly/RW8czT) is the component that will communicate with the resource server, provide the login controls and respond to a successful login, all without needing the Windows Store app to know anything about the user’s credentials. For the sample app, Contoso Photo Finish needs to post pictures to Facebook. This requires the user to authenticate to Facebook and receive an access token.

Add a new page control to the Contoso Photo Finish project called input.html. By default Visual Studio provides a lot of markup for you. Replace “<p>Content goes here.</p>” in the Main content section with the following button:

<input type="button" id="btnAddRun" value="Add Run" />

This is the button the user will click to add a run to Photo Finish. Now open input.js and add the following function:

function btnAddRun_Click(e) {
  var facebookOauthUrl = "https://www.facebook.com/dialog/oauth";
  var facebookClientId = "[YOUR CLIENT ID]";
  var redirectUrl = "https://www.facebook.com/connect/login_success.html";
  var requestUri = Windows.Foundation.Uri(facebookOauthUrl +
    "?client_id=" + facebookClientId +
    "&redirect_uri=" + encodeURIComponent(redirectUrl) +
    "&response_type=" +
    "token&scope=read_stream,publish_actions&display=popup");
  var callbackUri = Windows.Foundation.Uri(redirectUrl);
  // Web authentication broker will go here
}

This code establishes the variables that will be used in the authen­tication request. The first variable is the URL of the Facebook OAuth service. Client ID is the app identifier used by Facebook to identify Contoso Photo Finish as the app with which the Facebook API will interact. An identifier such as this is normally assigned to an app when it’s registered with the resource server. Some resource servers refer to the identifiers as client id, app id or just id. Which id to use will be found in the resource server’s API documentation.

The redirectUrl parameter determines where the app will go after the user authenticates and approves the app’s access to specified resources. In this case the redirectUrl is set to a Facebook standard that’s available to all Facebook API apps. Some services require the Windows Store app’s URI to be identified with the resource server when the app is registered. The app’s URI can be found using the Web authentication broker’s getCurrentApplicationCallbackUri method. This will return the app’s local context URI (beginning with “ms-app://”). Some resource servers don’t support ms-app:// as a valid protocol for a redirectUrl, in which case you should check for a default redirect address such as what Facebook provides.

Next, the callbackUri is defined. This is the address that informs the Web authentication broker when authentication is complete and returns control back to the Windows Store app. The broker never actually goes to this URL; it simply watches for the resource server to call for this page and then returns the callbackUri with any query string or hash parameters that were appended. In this case, the hash parameter “access_token” will provide Contoso Photo Finish the token needed to interact with the API.

The WebAuthenticationBroker class uses the authenticateAsync method to connect to and complete the authentication process with the resource server. When authenticateAsync is called, the app opens a pop-up that displays the resource server’s login screen, as shown in Figure 2. Once authentication is complete or the callbackUri is encountered, the pop-up will close.

Resource Server’s Login Pop-up from authenticateAsync
Figure 2 Resource Server’s Login Pop-up from authenticateAsync

A key advantage to using this pop-up is that the Windows Store app never handles or needs to know the user’s credentials for the resource manager. All the app knows is the access token that’s returned by the resource server. This separation keeps the resource server’s credentials isolated from the app, which avoids the security risk of the app storing the credentials. On top of the security benefits, the developer doesn’t have to code anything to get this interface; it’s built in to the authenticateAsync method. When developers call the method, the interface comes with it.

Now, back to code. Replace the “Web authentication broker will go here” comment with the following code:

Windows.Security.Authentication.Web.WebAuthenticationBroker.
  authenticateAsync(Windows.Security.Authentication.Web.
  WebAuthenticationOptions.none, requestUri, callbackUri)
.done(
  function (result) {
    // Check the response status here                 
  },
  function (ex) {
    Log(ex);
  }
);

The authenticateAsync method takes three parameters (the third is optional):

  1. WebAuthenticationOptions: This is used to provide instructions to the Web authentication broker on how to render the authentication dialog or what data to return in the response. In the preceding example, the app uses “none” to show a common implementation that passes no options to the broker using a default setup.
  2. requestUri: This is the login entry point for the resource server. In this case, Contoso Photo Finish is connecting to Facebook’s OAuth service. RequestUri must be over a secure connection using the HTTPS protocol.
  3. callbackUri: This is the page that, when navigated to, returns control back to the Web authentication broker as described earlier. This argument is optional, but if the resource server can’t (or won’t) redirect to ms-app://, this parameter is how the app will escape the resource server’s control. For example, in the earlier code when https://www.facebook.com/connect/login\_success.html is navigated to after a successful login, the Web authentication broker will take control of the app from the resource server by closing the authentication dialog and processing the success of the promise. CallbackUri doesn’t have to be in the immediate next page; it could be after a wizard or some other process that must occur on the resource server’s site. This URI will normally be the same as the redirectUrl but provides the flexibility to extend the authentication process, if necessary.

If the Web authentication broker connects to the resource server, the promise succeeds. Detecting the result of the authentication process is done through the WebAuthenticationResult object’s ResponseStatus property. In the preceding code, the result argument is a WebAuthenticationResult object with three properties: Response Data (data from the resource server), ResponseErrorDetail (if something went wrong, what was it?) and ResponseStatus (what’s the status of the authentication?). Replace the “Check the response status here” comment with the code shown in Figure 3.

Figure 3 Working with the Result of the Authentication Process

switch (result.responseStatus) {
  case Windows.Security.Authentication.Web.WebAuthenticationStatus.success:
    var fragment = Windows.Foundation.Uri(result.responseData).fragment;
    if (fragment.indexOf("#access_token=") != -1) {
      var token = fragment.substring(
        new String("#access_token=").length,
        fragment.indexOf("&expires_in="));
      // Add API calls here
    }
    break;
  case Windows.Security.Authentication.Web.WebAuthenticationStatus.userCancel:
    Log(window.toStaticHTML(result.responseData));
    Display("User cancelled the authentication to Facebook.");
    break;
  case Windows.Security.Authentication.Web.WebAuthenticationStatus.errorHttp:
    Log(window.toStaticHTML(result.responseData));
    Display("An error occurred while communicating with Facebook.");
    break;
}

In the Figure 3 code, each status is checked, with the Log method recording the information from the resource server and the Display method telling the user what has occurred. For error messages, remember to display user-friendly messages to improve usability and reduce accidental exposure of sensitive information from a system-generated error message. If the authentication is successful, the URI fragment returned from Facebook is parsed and stored in the token variable for use in the API call (see the “Getting and Posting Information via XHR” section for implementation details).                

With the btnAddRun_Click function complete, connect it to the btnAddRun object in the WinJS.UI.Pages.define { ready } function:

var btnAddRun = document.getElementById("btnAddRun");
if (null != btnAddRun)
  btnAddRun.addEventListener("click", btnAddRun_Click, false);

At this point the app has an access token showing that the user is authenticated to the resource server. In the last section the app will execute API commands to send data, but first the app needs something to send to Facebook.

Getting the Picture

Windows 8 provides a variety of contracts that allow apps to talk with each other, such as search, share and file picker. These contracts can turn any app into a mashup with just a few lines of code. Contoso Photo Finish is going to tap into the power of the file picker contract to find an image for the user’s run.

One of the many things I love about my Windows Phone is the integration with SkyDrive. I can upload my photos instantly to storage in the cloud so the next time I break my phone (which is often), my pictures are waiting for me online. The SkyDrive app for Windows 8 provides data to the file picker, making the selection of files from my SkyDrive account as simple as selecting them from the picture library. The next part of the Contoso Photo Finish mashup will consume data from the SkyDrive app through the file picker. To do this, input.html needs some, well . . . inputs.

Replace the btnAddRun button with the code shown in Figure 4. This code includes the input fields for the user to provide content for Contoso Photo Finish. The btnSelectPhoto button will use the file picker to select which file on the system to use. Add a new function to input.js that will be the click handler for btnSelectPhoto:

function btnSelectPhoto_Click(e) {
  var imgSelectedPhoto = document.getElementById("imgSelectedPhoto");
  var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
  filePicker.fileTypeFilter.replaceAll([".jpg", ".jpeg", ".png"]);
  filePicker.suggestedStartLocation =
    Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
  filePicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
  // Pick file here
}

Figure 4 Input Fields to Provide Content for the App

<p>
  <label>Distance</label>
  <input type="number" min="0" max="15" id="txtDistance"
    required /> miles
</p>
<p>
  <label>Comment</label>
  <input type="text" min="0" max="15" id="txtComment" />
</p>
<p>
  <label>Photo</label>
  <input id="btnSelectPhoto" value="Select Photo" type="button" />
  <img src="" id="imgSelectedPhoto" alt="Selected Photo" />
</p>
<p>
  <input type="button" id="btnAddRun" value="Add Run" />
</p>

The function begins by setting up the imgSelectedPhoto variable, which will be used to display the selected photo to the user. Next, the code creates a file picker object. The file picker object allows Contoso Photo Finish to choose files or folders (in this case just files) on the system or in other apps participating in the file picker contract to open and interact within the app. By using the file type filter, the code limits which file extensions are accessible to the file picker. The app can only load images to Facebook (by design), so limiting the file picker to only work with specified image file types keeps the user from selecting files that have invalid extensions that don’t meet the desired functionality. Also, due to the app’s focus on images, the file picker’s start location is set to the picture library. This could be a variety of default locations (such as music library, document library, home group and so on), but when dealing with pictures, the picture library is a common-sense starting point. The last setting for the file picker is to set the viewMode to thumbnail. This displays a preview of the file and is ideal for image selection.

With the options set, it’s time to select the file to use for the run. First, add these two variable declarations directly below the “use strict” statement:

var selectedPhotoStream = null;
var selectedPhotoFile = null;

These will hold the file and stream values for the btnAddRun_Click function when the data is loaded to Facebook. Now replace the “Pick file here” comment with the code shown in Figure 5.

Figure 5 Picking a File

filePicker.pickSingleFileAsync().then(
  function (storageFile) {
    if (storageFile) {
      selectedPhotoFile = storageFile;
      selectedPhotoFile.openAsync(
        Windows.Storage.FileAccessMode.read).then(
        function (stream) {
          selectedPhotoStream = stream;
        document.getElementById("imgSelectedPhoto").src =
          URL.createObjectURL(selectedPhotoFile);
      },
      function (ex) {
        Log(ex);
        Display("An error has occurred while reading the file.");
      });   
     }
    else {
      Display("File was not selected");
    }
  });

Figure 5 looks like a lot of code, but it boils down to three actions:

  1. Select the file that the app will be using via the file picker (pickSingleFileAsync).
  2. Open the file stream to be read (openAsync).
  3. Store the stream and file into variables for later use.

All of the code is standard for working with files and streams with one exception: URL.createObjectURL takes an object and builds a URL for the object to be displayed through an image object. The createObjectURL method works with many object types including Stream, StorageItem and MediaCapture. In general it’s used to display media content (image, audio or video) in a Windows Store app. One thing to keep in mind when using createObjectURL is that when you’re finished using the URL, make sure to dispose of it through the URL.revokeObjectURL method. This will ensure optimal memory usage and prevent the Windows Store app from getting bogged down with too many temporary URLs. For more information about createObjectURL, check out the MSDN documentation at bit.ly/XdhzOm.

Finally, associate the btnSelectPhoto_Click event with the btnSelectPhoto object. Add the following code in the WinJS.UI.Pages.define { ready } function:

var btnSelectPhoto = document.getElementById("btnSelectPhoto");
if (null != btnSelectPhoto)
  btnSelectPhoto.addEventListener(
    "click", btnSelectPhoto_Click, false);

At this point, Contoso Photo Finish has content to post and I have the mechanism to authenticate to Facebook for posting. Now the app just needs to interact with the API and throw the content online.

Getting and Posting Information via XHR

Remember when AJAX was new and exciting? XHR came on to the scene in Internet Explorer 5.5 and made Web developers start to rethink how Web apps were being made. Time passed and AJAX grew with many different libraries (such as jQuery) into an easy-to-understand and (more important) easy-to-implement solution. WinJS.xhr continues this tradition with a simple API to get and post data to online services.

Return to the btnAddRun_Click function and replace the “Add API calls here” comment with the code shown in Figure 6.

Figure 6 Generating a Blob Object from selectedPhotoStream

var fileBlob = MSApp.createBlobFromRandomAccessStream(
  selectedPhotoFile.contentType,
  selectedPhotoStream);
var message = "I just ran " + document.getElementById(
  "txtDistance").value + " miles with PhotoFinish! " + 
  document.getElementById("txtComment").value;
var data = new FormData();
data.append("source", fileBlob);
data.append("filename", selectedPhotoFile.name);
data.append("access_token", token);
data.append("message", window.toStaticHTML(message));
WinJS.xhr({
  type: "POST",
  url: "https://graph.facebook.com/me/photos",
  data: data,
}).then(
  function (photoid_response) {
    ProcessResponse(photoid_response);
  },
  function (ex) {
    Display("An error occurred while posting the photo.");
    Log(ex);
  });

Earlier, the app stored the StorageFile and Stream into the selectedPhotoFile and selectedPhotoStream variables. MSApp.createBlobFromRandomAccessStream takes the selectedPhotoStream and generates a Blob object (bit.ly/Stfu9z) that the app will later pass to Facebook as a POST parameter. This is a useful feature for converting WinRT objects into a format that can be transferred via HTTP.

Next, the code uses the FormData object (new to HTML5) to create the parameters that will be sent in the HTTP POST. FormData is a key/value pair object with just one method: append. Using the append method, developers can build form fields dynamically and submit them with a POST as if the form’s submit event was called. FormData also provides the parameters as if they belonged to a form with multipart/form-data encoding. This allows developers to post any input type (including files) to the target server.

Notice in the FormData.append method call that I use toStatic­HTML (bit.ly/ZRKBka) to ensure that the message content is safe for delivery. Using toStaticHTML will remove any event attributes or script content from the message variable prior to adding it to the FormData object. While I imagine Facebook is good about preventing cross-site scripting attacks (among others), as a mashup developer, I want to provide clean content to my fellow apps. The Internet is a big place, so we all need to watch out for each other.

The rest of the code block is the WinJS.xhr call. This time around, the code uses some more attributes of XHR, including:

  • type: This sets the HTTP method to be used. By default type is set to GET. This code uses POST because the app is sending content to the Facebook API.
  • data: This consists of parameters to pass with the POST.

When the promise is returned in the success method, Contoso Photo Finish processes the photo ID for later retrieval. If an error occurs, the standard error message is displayed and the exception is logged.

WinJS.xhr is a lot like other XHR wrappers. If you’re familiar with JavaScript libraries such as jQuery, you’ll be able to pick up WinJS.xhr easily. One gotcha that you could encounter is that, unlike XHR, there’s no timeout option on the WinJS.xhr method. Setting a timeout is accomplished by wrapping the WinJS.xhr call with a WinJS.Promise.timeout method (bit.ly/Qgtx7a). By adding the following code to the beginning of the WinJS.xhr call, I set a timeout of 10 seconds to the POST:

WinJS.Promise.timeout(1000, WinJS.xhr({ ... });

If the WinJS.xhr promise doesn’t complete within 10 seconds, the promise will timeout and be handled through the timeout promise’s error function.

First Steps in Mashing Your App

In this article I examined authenticating, getting files and sending data with WinJS and the Windows Runtime. These foundation skills can be built upon to design Windows Store apps that are limited only by your imagination and developer keys. Take the material in this article and explore your favorite online service. Using WinJS.xhr, your Windows Store app can interact with the countless APIs available online. With the Web authentication broker, your app can connect users with their online personalities, content and communities using OAuth or OpenID. WinJS and the Windows Runtime give you all the tools to easily build an app that’s greater than the sum of its online services.


Tim Kulp leads the development team at FrontierMEDEX in Baltimore. You can find Kulp on his blog at seccode.blogspot.com or on Twitter at Twitter.com/seccode, where he talks code, security and the Baltimore foodie scene.

Thanks to the following technical experts for reviewing this article: Sunil Gottumukkala and Jeremy Viegas