Thursday 11 June 2015

Calling Office 365 Unified API (Preview) from Java script using ADAL for JS

Office 365 unified API provides developers with a single endpoint for accessing all Office 365 data and relationships, including Users, Groups, Files, Mail, Calendar, Contacts and Office Graph. Office 365 Unified API removes the complexity in accessing Office 365 data and makes development simpler. Developers have a choice of calling the REST API or use client libraries that are available for .Net, Android and iOS platforms.  In this blog I’ll explain the process of calling the Office 365 Unified from Java script using ADAL for JS.

For developing a Java script application with Office 365 Unified API the below prerequisites have to be met

1.       Web site development tool of your choice(Visual Studio in my case)
2.       Office 365 Tenant ( Trial subscription can be used)
3.       Microsoft Azure Tenant (Trial subscription can be used).

Note: The Azure subscription should be tied to the Office 365 account.

Once we have the prerequisites ready we can start with development of the application.  The first step is to register the application Azure.

Register the application Microsoft Azure

  1. Logon to Azure Management Portal, using your Azure AD credentials.
  2. Click Active Directory on the left menu, then select the directory for your Office 365 tenant.
  3. Click Applications from the top menu.
  4. Click Add from the bottom tray.
  5. On the What do you want to do? page, select Add an application my organization is developing.
  6. On the Tell us about your application page, enter the application name as O365UnifiedAPIWithJavaScript and select the type as Web application and/or web API.
  7. Click the arrow on the bottom right to move to next page.
  8. On the Application information page, specify the app SIGN-ON URL and APP ID URI and then click the tick mark on bottom right. The SIGN-ON URL is our app's web address including the port number. For example http://localhost:55389/start.html.  For the App ID URI, enter https://<tenant_name>/O365UnfiedAPIWithADALJS where <tenant_name> is the name of Azure AD tenant.
  9. Once the application has been added, you will be taken to the Quick Start page for the application. From the application page, click Configure from the top menu.
  10. Copy the value specified for Client ID on the Configure page and save it to notepad or similar tool.
  11. Click Add application button under permissions to other applications section and in the dialog box that opens, select the Office 365 unified API (preview) application and click the tick mark on bottom right.
  12. On the application configuration page, select Office 365 unified API (preview) and select Read users’ files permission.
 
 13. Click Save in the bottom menu.

Now that the app has been registered in Azure we can start developing the Java Script application. For this example I will be using a Java Script application that lists files from users One Drive.

1.       Start Visual Studio and create an empty ASP.Net web project.
 
2.       Add a new HTML file to the project and name it as start.html. Add button input elements to the page for login, logout and showing files. Add pre elements for showing the result, error and loading message.

3.       The content of start.html will be similar to

<html>
<head>
    <title>Office 365 Unified API and ADAL JS</title> 
</head>
<body >

    <div>
        <input type="button" id="btnLogin" value="Login">
        <input type="button" id="btnLogout" value="Logout" hidden>
        <br />
        <pre id="lblUser"></pre>
        <input type="button" id="btnFiles" value="Show Files" hidden>
        <br />
        <pre id="lblLoading" hidden>Loading Files...</pre>
        <pre id="lblFiles" hidden></pre>
        <pre id="lblError" hidden></pre>
    </div>
    <br />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/adal.min.js"></script>
    <script src="Scripts/app.js"></script>
</body>
</html>
 
4.       Add reference to ADAL. and JQuery JS from CDN source

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/adal.min.js"></script>
5.       Add a java script file with the name app.js to the project. This file will have the code that connects to office 365 unified API via ADAL and list the files from users One Drive.
6.       adal.js exposes a class AuthenticationContext that handles the authorization and token acquisition process. Within our app.js we initialize the AuthenticationContext class by passing the configuration values
      configuration = {

        tenant: '<tenant_name>',

        clientId: '<client_ID>',

        postLogoutRedirectUri: '<redirect URL>',

        endpoints: 'https://graph.microsoft.com',

        cacheLocation: 'localStorage',

      };

      var authContext = new AuthenticationContext(configuration);
In the code above tenant is <tenant_name> is the name of Azure AD tenant, <client_ID> is the client ID of the App we have copied from Azure App configuration page, <redirect URL> is the url to which the Azure will redirect after login.

7.       Then we create a method called ShowFiles that will be invoked with the show files button on the HTML page is clicked.  Within this method will write code to call the Office 365 unified API end point https://graph.microsoft.com to acquire token and the use to token to make subsequent call to the files endpoint https://graph.microsoft.com/beta/me/files . If the call to files endpoint is successful we loop through the response to form a HTML table that lists the files.

8.       The complete code in app.js will be similar to

(function () {
      configuration = {
        tenant: 'tenant_name',
        clientId: 'client_id',
        postLogoutRedirectUri: 'redirect url',
        endpoints: 'https://graph.microsoft.com',
        cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
      };

      var authContext = new AuthenticationContext(configuration);

    var $loginButton = document.getElementById("btnLogin");
    var $logoutButton = document.getElementById("btnLogout");
    var $filesButton = document.getElementById("btnFiles");
    var $lblUser = document.getElementById("lblUser");

    // Handle Redirect From AAD After Login
    var isCallback = authContext.isCallback(window.location.hash);
    authContext.handleWindowCallback();
    //$errorMessage.html(authContext.getLoginError());

    if (isCallback && !authContext.getLoginError()) {
        window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
    }

    // Hide and show elements based on login status
    var user = authContext.getCachedUser();
    if (user) {
      
        $loginButton.hidden = true;
        $logoutButton.hidden = false;
        $filesButton.hidden = false;
        $lblUser.innerText = "Welcome " + user.profile.name;
    } else {
    
        $loginButton.hidden=false;
        $logoutButton.hidden = true;
        $filesButton.hidden = true;
        $lblUser.innerText = "";
    }

 //Add event handlers for button clicks
    $loginButton.onclick = function () {
                authContext.login();
    };

    $logoutButton.onclick = function () {
        authContext.logOut();
    };

    $filesButton.onclick = function () {
        ShowFiles();
    };

    //Get files from OneDrive and list in a table
    function ShowFiles() {
        // Empty old view contents.
        var $lblLoading = document.getElementById("lblLoading");
        var $lblError = document.getElementById("lblError");
        $lblLoading.hidden = false;
                console.log("Fetching files from OneDrive...");
        // Acquire token for Files.
                authContext.acquireToken('https://graph.microsoft.com', function (error, token) {

                    // if there is an error in ADAL
                    if (error || !token) {
                        $lblError.innerText = 'ADAL exception : ' + error;
                        
                        return;
                    }
                    $.ajax({
                        type: "GET",
                        url:  "https://graph.microsoft.com/beta/me/files",
                        headers: {
                            'Authorization': 'Bearer ' + token,
                        }
                    }).done(function (response) {

                        var output = '<table cellspacing="0" cellpadding="5" border="1"><tr><th>File Name</th><th>Type</th></tr>';
                        //Loop through response and form files HTML output
                        response.value.forEach(function (item) {                         
                            output += "<tr><td>" + item.name + "</td><td>" + item.type + "</td></tr>";
                        })
                        output += "</table>";
                        var $lblFiles = document.getElementById("lblFiles");
                        $lblLoading.hidden = true;
                        $lblFiles.innerHTML = output;
                        $lblFiles.hidden = false;
                        $filesButton.hidden = true;
                    }).fail(function () {
                        console.log('Problem in fetching files from OneDrive.');
                        $lblError.innerText = 'Problem in fetching files from OneDrive.';
                        $lblError.hidden = false;    
                    });
                });
    }
}());
 
9.       Add a reference to app.js in start.html

10.   Now if we open start.html in a browser a login button will be displayed clicking which will redirect to Azure login page. After successful authentication we will be taken back to start.html in our web application and the Show Files button will be displayed.

11.   Clicking the Show Files button will list the files stored in One Drive for the logged in user as shown below.