Using the Graph API to Query Windows Azure AD

4 out of 4 rated this helpful - ​​Rate this topic​

This document will explain how to configure a .NET application to use the Graph API to access Directory data from a Windows Azure AD Tenant’s directory.

Overview


This sample application is intended for .NET developers who want to add to existing applications and build new applications for Windows Azure Active Directory. This walkthrough builds upon the previous walkthrough, ​​Adding Sign-On to Your Web Application Using Windows Azure AD​​, which produced a sample app that demonstrates how to provide a web single sign-on user experience for Windows Azure AD customers. This document will show how to add capability to read directory data using the Windows Azure AD Graph API. The Graph API is a new RESTful API that allows applications to access customers’ Windows Azure directory data.

Applications need access to directory data for many scenarios including:


  • Retrieving lists of users, groups, contacts for people/group pickers
  • Reading detailed tenant, user and group information
  • Verifying Group membership
  • Modifying user and groups, group membership
  • Updating a user’s password
  • Disabling user accounts


Outline of Sections


This document is organized into the following sections:


Prerequisites


This following prerequisites are required to complete this tutorial:


Solution Architecture


At the end of this walkthrough, you will have an application that is configured to read data from your tenant hosted in Windows Azure Active Directory. Directory entities that can be read include Users, Groups, Contacts, Company Information, Licenses, and Roles. Several of these directory entities’ properties can also be updated if your application is granted write Permissions.

In this sample application, we’ll review how to read directory data from your Windows Azure AD company. Additional advanced topics include:


  • Getting full user details
  • Creating and Updating Users
  • Getting a list of groups
  • Updating group membership

Authentication and Accessing the Graph API


The single sign-on experience remains the same after updating this application for accessing the Graph API. After successful user authentication, the application start the process of calling the Graph API by first requesting a token from Windows Azure AD Authentication endpoint, and once successful, the app will use the token in the subsequent Graph API call to get all users from the tenant. The application will then display a list of users, showing their Display Names and User Principal Names.


Application Authentication and Authorization for the Graph API


In this walkthrough, we will be using the OAuth 2.0 client credential flow to authenticate the application. Before accessing the Graph API endpoint, the application must first acquire a valid token from Windows Azure Active Directory’s Authentication endpoint -- it does this by presenting valid application credentials (Client ID and Secret). If the credentials are validated, a signed token is returned to the application. The application will then include the token in its Authorization header in its calls to the Graph API. The Graph API service will validate the token against the incoming request, and if this passes, then an authorization check occurs next.

Application authorization is verified by the Graph API and its underlying Role Based Access Control (RBAC) service. Calls to the Graph API are limited to the permissions that are configured to the application. Data is returned to the application if authentication and authorization passes.


Configuring Application Authentication and Authorization for the Graph API


An application’s authentication and authorization configuration are stored in Windows Azure AD using a Service Principal object stored in tenants’ directory. Similar to how users are represented by User Principal objects stored in tenants’ Active Directory, each having unique identities, credentials and permissions, an application in Windows Azure AD is represented by a Service Principal object, with a unique identity, credential and permissions.

An application’s Service Principal is configured to have a unique ID and Secret, which is used for authentication. Authorization is managed by adding the application’s Service Principal to a role that has the required permissions. Creating application Service Principals and adding them to roles can be done by Tenant Administrators using the Windows Azure AD Management Portal. Optionally, Tenant Administrators can also use PowerShell to manage Service Principals.

In the previous single sign-on walkthrough, you authorized the application to allow single sign-on using your Windows Azure AD user credentials by configuring the app permissions in the Windows Azure AD Management Portal. You will now update the application configuration to enable this walkthrough application to authenticate, and be authorized to call the Graph API. The following steps should be executed:


  • Authorization: configure your app permissions to allow read/write access to the directory.
  • Authentication: get an Application Key, which is your application’s password and used to authenticate your application to the Graph API.

Authorization – Configure the Application to Allow for Read and Write Permissions



  1. Log on to the Windows Azure Active Directory Management Portal and find the sample application you created in the single sign-on walkthrough.




  2. Select the MANAGE ACCESS button on the bottom of the screen.
  3. On the What do you want to do? screen, select Change the directory access for this app.



  4. On the next screen, select the radio button next to SINGLE SIGN-ON, READ DIRECTORY DATA, then check button in the bottom right-hand corner of the screen to save your changes.




Authentication – Configure the Application Key



  1. From the main application page, expand Enable your app to read or write directory data, then under the CREATE A KEY section, select the Configure key option.




  2. Next on the Properties page, under the Keys section, add a key by selecting the key’s lifespan (default 1 year), and then select Save at the bottom of the screen. This will generate a key value that is your application’s password and will used in the application configuration.

The key value is displayed after key creation, but cannot be retrieved later. Therefore, you should immediately copy the key value and store it in a secure place for your future reference. Also, your application can have multiple keys –- for example, you may want one or more for testing and production.







At this point you have a Client ID (Application ID), an application key (the key value) and have configured read and write permissions for the application.


In this walkthrough sample application, we are using the key values as a password to authenticate the application (in OAuth 2.0 terms, are using the Client credentials grant flow, where ​​grant_type=client_credentials​​).





Adding Graph API Access to the MVC 4 Single Sign-On Walkthrough Application


Open Visual Studio, then open the single Sign-on walkthrough project that you previously built. We will be modifying the sign sign-on walkthrough application in the following steps:


  1. Add the Graph helper class project
  2. Update to WCF Datservices 5.3 or greater
  3. Update the Web.config file
  4. Modify the HomeController
  5. Add a new View for Users
  6. Update the common _Layout View

Add Graph Helper Class Project to the Single Sign-On Walkthrough Application


The Graph Helper class project includes a library and classes that facilitate authenticating to and calling the Graph API. It includes source code and should be included and built as part of this walk-through. ​​Download the Graph Helper project​​.


  1. To add the Graph Helper to the single sign-on project, right-click the ExpenseReportsolution, click Add, then click Existing Project.
  2. From the Add Existing Project dialog, navigate to the Graph Helper path, then open theMicrosoft.WindowsAzure.ActiveDirectory.GraphHelper.csproj project file.

The Graph Helper project will be added to your ExpenseReport solution.


Update the Existing Single Sign-On Application’s Web.config File


The appSettings section of the Web.config file has application specific configuration information – add the ClientId and Password values to the application’s Web.config file.


  • ClientId: equal to the Client ID value from the Windows Azure AD Management Portal application management page.
  • Password: equal to the Application Key Value from the Windows Azure AD Management Portal Application management page. This should have been recorded from the previous step to create a key – note this is not retrievable. If you forgot or lost the previous key, create another under the same application.


<appSettings>     <add key="ClientId" value="<insert your ClientId here>"/>     <add key="Password" value="<insert your Application Key here>"/>     ...


Save the Web.config file after making the changes.


Update the Project’s References



  1. From Visual Studio, right-click on the single sign-on walkthrough project’s Referencesfolder, then click Add Reference…
  2. On the Reference Manager dialog, click Extensions from the left menu, then click the checkbox next to the Microsoft.Data.OData version 5.3.0.0 assembly and theMicrosoft.Data.Services.Client version 5.3.0.0 assembly.



  3. In the same Reference Manager dialog, expand the Solution menu on the left, then click the checkbox for the Microsoft.WindowsAzure.ActiveDirectory.GraphHelper. PressOK, then the references will be added to your project.



Update the HomeController


Open the HomeController.cs file, which is in the Controllers folder. Add the following assemblies to the file, then save the file.

C#

using System.Configuration; using System.Security.Claims; using System.Data.Services.Client; using Microsoft.WindowsAzure.ActiveDirectory; using Microsoft.WindowsAzure.ActiveDirectory.GraphHelper;


Find the HomeController class in the HomeController.cs file, where the existing ActionResultsreside (Index, About, Contact). Add a new ActionResult called Users as shown below:


public ActionResult Users()        {             //get the tenantName             string tenantName = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;                // retrieve the clientId and password values from the Web.config file             string clientId = ConfigurationManager.AppSettings["ClientId"];             string password = ConfigurationManager.AppSettings["Password"];                // get a token using the helper             AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantName, clientId, password);              // initialize a graphService instance using the token acquired from previous step             DirectoryDataService graphService = new DirectoryDataService(tenantName, token);              //  get Users             //             var users = graphService.users;             QueryOperationResponse<User> response;             response = users.Execute() as QueryOperationResponse<User>;             List<User> userList = response.ToList();             ViewBag.userList = userList;               //  For subsequent Graph Calls, the existing token should be used.             //  The following checks to see if the existing token is expired or about to expire in 2 mins             //  if true, then get a new token and refresh the graphService             //             int tokenMins = 2;             if (token.IsExpired || token.WillExpireIn(tokenMins))             {                 AADJWTToken newToken = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantName, clientId, password);                 token = newToken;                 graphService = new DirectoryDataService(tenantName, token);             }              //  get tenant information             //             var tenant = graphService.tenantDetails;             QueryOperationResponse<TenantDetail> responseTenantQuery;             responseTenantQuery = tenant.Execute() as QueryOperationResponse<TenantDetail>;             List<TenantDetail> tenantInfo = responseTenantQuery.ToList();             ViewBag.OtherMessage = "User List from tenant: " + tenantInfo[0].displayName;               return View(userList);        }


Add a new View for Users


Create a new view under the Views/Home folders called Users.cshtml, and add the following code:

C#

@model IEnumerable<Microsoft.WindowsAzure.ActiveDirectory.User>  @{     ViewBag.Title = "Users"; }  <h1>@ViewBag.Message</h1> <h2>@ViewBag.OtherMessage</h2> <table>     <tr>         <th>             DisplayName         </th>         <th>             UPN         </th>         <th></th>     </tr>  @if (User.Identity.IsAuthenticated) {    foreach (var user in Model) {     <tr>         <td>          @Html.DisplayFor(modelItem => user.displayName)             </td>         <td>          @Html.DisplayFor(modelItem => user.userPrincipalName)         </td>    </tr>   } } </table>


Update the _Layout.cshtml View


Find and open the _Layout.cshtml file under the Views/Shared folder, and add the following<nav> section within the <header> section of the file. Then, save the file.


<nav>                         <ul id="menu">                             <li>@Html.ActionLink("Home", "Index", "Home")</li>                             <li>@Html.ActionLink("About", "About", "Home")</li>                             <li>@Html.ActionLink("Contact", "Contact", "Home")</li>                             <li>@Html.ActionLink("Users", "Users", "Home")</li>                         </ul>                     </nav>


Run the Application


Press F5 to run the application. The single sign-on experience is the same as you saw in the previous walkthrough, requiring authentication using your Windows Azure AD credentials. If you published your application to a website, you should update it with the updates from this walkthrough. After successful user authentication, select the Users tab from the top right menu.

The application starts the process of calling the Graph API by first requesting a token from Windows Azure AD Authentication endpoint. Once this is successful, it will use the token in the subsequent Graph call to get all users from the tenant. The application will then display a list of users, showing their Display Names and User Principal Names.

This concludes the coding for the Graph API walkthrough application. The next section includes more detailed information and links to a more advanced Graph API sample application that shows additional read and write operations.


Advanced Topics Section


Application Execution


After successful single sign-on, the application will request a token from the Windows Azure AD Authorization endpoint, using the tenant name (obtained from the signed on user’s tenant ID claim), ClientID and Password to authenticate. The details of the method that supports the token acquisition can be found in the DirectoryDataServiceAuthorizationHelper class found in the file of the same name. The GetAuthorization method manages acquiring the JSON Web Token (JWT) token from Windows Azure AD Authentication by providing a valid tenant name (any verified domain owned by the tenant), Client ID and the Password.

A successful request will return a JWT token to be used in calls to the Graph API, which is inserted in the Authorization header of subsequent requests. The Graph API call to get all users is an HTTP GET request that contains the following headers:


Content-Type: application/json; odata=minimalmetadata Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T….


It is recommended that the JWT token be cached by the application for subsequent calls – in the sample application, the JWT token expiration is checked before making a second Graph API call. If the token is expired, then a new token is acquired. If a call to the Graph API is made with an expired token, the following error response will be returned, and the client should request a new token.


HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="contoso.com", error="invalid_token", error_description="Your access token has expired. Please renew it before submitting the request.",


Currently there is a preview of Windows Azure Authentication Library (AAL) which manages the acquisition of the Windows Azure AD authentication tokens. When AAL is released, we will update our sample applications and documentation to use AAL. The documentation for the AAL preview is ​​located here​​.





Other Advanced Topics


Additional REST calls, including read and write methods, can be found in another MVC4 Sample application that can downloaded from ​​here​​.

This sample demonstrates additional REST functionality including:


  • Get and Set User Details, including thumbnail photos
  • Create, Update Groups
  • Update Group Membership
  • Paging for handling a large number of returned objects