Using the Office 365 APIs from a SharePoint App

Scot Hillier

by Scot Hillier on 12/17/2014

Share this:

Article Details

Date Revised:

Applies to:
app permissions, Azure Active Directory, Office 365 APIs, SharePoint app

Sponsored by

After finishing my recent article on Programming with the Office 365 APIs General Availability Release, I received a few queries asking how to use the Office 365 APIs within a SharePoint app. In this article, I’ll show you the current approach for using the Office 365 APIs within a SharePoint app. More importantly, however, I’ll discuss the current state of developing across SharePoint and Office 365 and give you a glimpse into the future. You’ll see that there are definitely challenges with the current state of affairs, but hope is on the horizon.

For the example in this article, I’ll create an app part that reads the current user’s appointments from Exchange and displays them on a page in SharePoint (Figure 1). Because app parts run in an IFRAME, some of the key security challenges will become painfully obvious – but more on that as I build the sample. You can download the complete code for the example here.

SharePoint app reads appointments from Exchange

Figure 1, The app part built in this article

Understanding security challenges

In order to get started, I’ll create a provider-hosted app project using a SharePoint site in my Office 365 tenancy as the host. After I’ve created my project, I can open the web.config file in the remote web project and see that my app has an assigned ClientId and ClientSecret (Figure 2). One of the key aspects of SharePoint apps is that they are first-class security principals, and the ClientId/ClientSecret combination is effectively the assigned username and password for the app. This is, of course, a normal and expected outcome that doesn’t have any direct relationship to the Office 365 APIs; I’m simply calling it out here because it will be important later.

Provider-hosted app ClientId and ClientSecret

Figure 2, Provider-hosted app ClientId and ClientSecret

As with any SharePoint app, I can also assign permissions through the AppManifest.xml file located in the app project. Again, there is nothing special here with regards to the Office 365 APIs. You can simply assign any required permissions such as the ability to read items in the host web (Figure 3). Just like the security principal information, however, this will become important momentarily.

Assign app permissions

Figure 3, Assigning app permissions

Once the base project is created, I can easily add Office 365 API functionality in the normal way. I’ll simply right-click the remote web project and select Add/Connected Service. This brings up the Services Manager dialog (Figure 4) where I can register my app and grant permissions. For this example, I’ll grant Read permissions to the user’s calendar. Clicking OK adds the required support for the Office 365 APIs to my SharePoint provider-hosted app.

Register calendar app and grant permissions

Figure 4, Granting Office 365 permissions

After adding Office 365 API support, I can open the web.config file for the remote web project and see that I now have additional security principal entries. Along with the ClientId and ClientSecret, I can also see ida:ClientID and ida:Password entries (Figure 5). This is because adding Office 365 API support to my SharePoint app caused the creation of a second security principal – and this is where things get messy.

ida:ClientID and ida:Password security principal entries

Figure 5, Office 365 ClientID and Password entries

Along with the second security principal, the app also gained permissions to read the current user’s calendar. However, this permission is not granted through the AppManifest.xml file like a normal SharePoint app. Instead, it is granted in Azure Active Directory.

In order to see these permissions, you must add the Azure Active Directory associated with your Office 365 tenant to your Azure subscription. This is done within the Azure portal by adding a new Active Directory instance and then opting to add an existing instance. Subsequently, you can look at the associated applications where you can examine the configuration for the registered app. You will see the same permissions here that are displayed in the Visual Studio tooling.

Set app permissions in Azure Active Directory

Figure 6, App permissions in Azure Active Directory

The implications of adding Office 365 API support to a SharePoint app is that your app now uses two separate security principals and must manage permissions in two separate places. This is a significant consequence because you effectively have two separate apps running as one. Additionally, the tokens used to access SharePoint resources are different from the tokens used to access Office 365 resources; they cannot be used interchangeably and must be managed separately in code. Worst of all, the app will prompt twice for consent: once during the initial app installation, and once when the app asks for user consent to access Exchange. This is certainly not an ideal situation.

The good news is that Microsoft is working hard to solve this problem. Within the next few months, I expect that a single security principal will be supported across SharePoint provider-hosted apps and Office 365. Sometime after that, I expect that there will be a unified way for registering apps and managing permissions. For now, however, this is the only way to combine SharePoint apps and Office 365 APIs in a single project. So, you should try to architect the app to minimize the number of prompts and round trips to the authorization server.

Programming the app

Once the Office 365 API support is in place, you can continue developing. For this app, I am going to add an app part to the remote web. I’ll do this is the usual way by right clicking the app project and selecting Add/New item. In the Add New Item dialog, I’ll select Client Web Part and then choose to add a new controller and view to my MVC5 remote web project.

At this point, I need to spend some time thinking about the authorization flow. I know that the current user will be prompted to give consent the first time they run the app. However, app parts run in an IFRAME, and the authorization flow doesn’t allow showing the required pages in an IFRAME. So, I am left with little choice other than to authorize the current user in the full-page app experience and cache the calendar events for display later. Listing 1 shows the code for retrieving and caching the events.

Listing 1, Retrieve and cache events

//Create an Outlook client
OutlookServicesClient outlookClient = 
new OutlookServicesClient(eventsDisco.ServiceEndpointUri, async () =>
    var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
        new Uri(Request.Url.AbsoluteUri.Split('?')[0]),
    return authResult.AccessToken;
//Get the events for the next 8 hours
var eventResults = await (from i in outlookClient.Me.Events
                          where i.End >= DateTimeOffset.UtcNow && i.End <= DateTimeOffset.UtcNow.AddHours(8)
                          select i).Take(5).ExecuteAsync();
var events = eventResults.CurrentPage.OrderBy(e => e.Start);
foreach (var e in events)
    eventList.Add(new MyEvent
        Id = e.Id,
        Body = e.Body == null ? string.Empty : e.Body.Content,
        End = e.End,
        Location = e.Location == null ? string.Empty : e.Location.DisplayName,
        Start = e.Start,
        Subject = e.Subject == null ? string.Empty : e.Subject
//cache the events
SaveInCache("Events", eventList);

Once the events are cached, the app part can simply read the data from the cache. If the data is not in the cache, then the user is redirected to the app’s full page experience to authorize. Alternatively, the web part could call AuthenticationContext.AcquireTokenByRefreshTokenAsync in order to get the freshest data on each display of the web part. Listing 2 shows the app part code.

Listing 2, App part code

List<MyEvent> eventList = GetFromCache("Events") as List<MyEvent>;
if (eventList == null)
    //Redirect to app web for authentication
    return Redirect(
    //Show contacts
    return View(eventList);

As I noted earlier in the article, the app will prompt for consent twice. The first time is when the app is installed by the site owner (Figure 7). The second is when the user is prompted for consent to allow reading the calendar (Figure 8).

grant permissions when app is installed

Figure 7, Consent during installation

grant permission to the app to read calendar

Figure 8, Consent during execution


In this article, I built an app part in a provider-hosted app that utilized the Office 365 APIs to read and display calendar events. Based on the development, some important conclusions can be made:

  1. Integrating the Office 365 APIs with a SharePoint app is done in the “normal” way by simply adding a connected service.
  2. Adding Office 365 API support requires the app to be registered with both SharePoint and Azure Active Directory resulting in two separate, unrelated security principals.
  3. Adding Office 365 API support means that app permissions will be managed in both SharePoint and Azure Active Directory.
  4. Adding Office 365 API support means that an app will prompt for consent both during initial installation and when run by the end user.
  5. The tokens used by SharePoint and Azure Active Directory are not interchangeable and must be managed separately.

While the current situation is challenging, Microsoft plans on simplifying this story in the near future. So, if you are planning on utilizing Office 365 APIs in your SharePoint apps today, be careful to create them in a way that can be upgraded when the story changes.

Topic: Development

Sign in with

Or register

  • Hi Scot
    Trying to reuse your code but i keep getting a page not found error when i deploy.any ideas where i could be going wrong?
  • Hi Scot
  • Hello! thank you very much for this article.
    An intresting thing is happening to my app with the exact same code.
    I downloaded the latest pachage of Microsoft.OData ( and it stopped working!!
    It hangs for ever on the line:

    var eventResults = await(from i in outlookClient.Me.Events
    where i.End >= DateTimeOffset.UtcNow && i.End <= DateTimeOffset.UtcNow.AddHours(8) select i).Take(5).ExecuteAsync();

    would you happen to know why this is happening?
    I updated the library on your sampe project as well and the same happened..

    thank you!!
  • Super article, Chris. Thanks for the reference. Interesting times for sure.
  • Hey Scot,

    Great article! It's definitely an interesting idea (i.e.*combining* the approaches of a SharePoint app and an Office 365 app within the same app). I wrote an article trying to make clear the big differences between the two models (e.g. around user experience, authentication/authorization etc.) at "Office 365 apps - deciding between the SharePoint app model and Office 365 apps" - In my head at least, your article works as a great "and now consider this!" after reading mine - but I have to say, my thinking at the moment is that most folks would choose one approach or the other.

    As you say, I'm sure this will all evolve in the near future though - and hopefully there is some simplification and convergence across the two models. Great work on illustrating the current situation!


  • Great, Jeremy - can't wait!
  • Nice write up Scot. If your Azure Active Directory Administrator actually assigns individual users (Groups coming soon), they won't be required to see the consent window. More convergence of these two authentication flows will be coming early next year. - See more at: