Building applications with the Office 365 APIs on any platform

dev.office.com banner
Thanks to Microsoft’s investments we can build add-ins and web apps on any platform, including platforms without dedicated Office 365 API SDKs.

To simplify building Office and SharePoint Add-ins and Web Apps using the Office 365 APIs Microsoft released SDKs and code samples for the most popular platforms. Those SDKs help you complete the authorization flow with Azure AD and simplify interacting with the different Office 365 APIs. Although SDKs for the most popular platforms are already available there still might be a chance that you are developing on a platform that doesn’t have an SDK available yet. The good news is that even in such case you can leverage your existing skills and connect your application to Office 365.

First things first

Interacting with Office 365 APIs is straight-forward. Office 365 APIs are all REST APIs and while not all of them are fully ODATA-compliant yet, there are very few intricacies and you should be able to get the data that you need without too much effort.

Before you will be able to do that however, you will need to have the user to authenticate with Azure AD and authorize your application to communicate with Office 365 APIs. SDKs that Microsoft released make it easy for you to complete the whole flow. If you’re developing on a platform that doesn’t have an SDK available yet however, you will need to complete this flow manually. The good news is that Office 365 APIs use OAuth so if you have experience with using this protocol, completing the authentication and authorization flow with Office 365 APIs won't be much of a problem.

Following are the steps that you will need to go through to get an access token to the specific Office 365 APIs. These steps assume that you have built a multi-tenant app (which is the type of app you would need to build to publish it to the Office Store) that uses the Discovery Service to get the endpoints and access tokens for the specific services. Using Office 365 APIs will be simplified in the future when the new Office 365 Unified APIs will be released. For now however you will need to follow the flow as described below.

Side note

Recently I’ve been doing some Node.js development. Although there are a few packages that simplify authenticating with Azure AD such as adal-node or passport-azure-oauth2, there is no dedicated Office 365 SDK for Node.js available yet. The packages I mentioned will help you connect to the Office 365 APIs. Still it is very helpful to understand the OAuth flow in case something doesn’t work as expected or if you want to achieve something which is not yet supported by the packages.

Although it is not required to use HTTPS if you’re building a web app, if you’re building Office Add-ins you do need to use HTTPS. HTTPS introduces a little overhead with regards to certificates and configuring your development environment. Still it is a good practice to ensure that you won’t experience problems later down the road.

Tip: If you’re looking into developing with Node.js on OS X Andrew Connell has a great post with the steps required to get a self-signed SSL certificate.

Getting the access code

The authentication flow begins with obtaining an access code. This is done by executing a GET request to the following URL:

https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&client_id=4f468d22-7e84-4a8c-af4e-747a450c0bc5&redirect_uri=https://localhost:8443/auth&session_state=cee9bc0c-015e-4745-8e0f-0af1c541dc33  

Because your application is multi-tenant, the URL contains common as the tenant ID rather than a specific tenant ID. The client_id query string parameter contains the ID of your application as registered in the Azure AD. The redirect_uri parameter specifies the URL which Azure AD will call with the access code. The URL specified in the redirect_uri parameter must match one of the callback URLs specified in Azure AD when registering your application. Finally the session_state parameter contains a unique identifier of the flow that you should use to compare with the identifier sent with the callback from Azure AD. If both identifiers don’t match there is a chance that someone is performing a CSRF attack and the auth flow should be aborted.

If the request was successful Azure AD will callback your application at the URL specified in the redirect_uri parameter:

https://localhost:8443/auth?code=AAABAAA...km1IgAA&session_state=cee9bc0c-015e-4745-8e0f-0af1c541dc33  

The code query string parameter contains the access code that you can exchange for an access token. The session_state parameter contains an identifier that you should check against the identifier you issued when calling the authorization endpoint. If the flow is correct both identifiers should match. If they don’t, you should abort the authentication process.

Exchanging the access code for an access token to the Discovery Service

To exchange the access code retrieved from the authorization endpoint for an access code issue a POST request to the following URL:

https://login.microsoftonline.com/common/oauth2/token  

Pass the following parameters as x-www-form-urlencoded:

client_id=4f468d22-7e84-4a8c-af4e-747a450c0bc5&client_secret=oIa4kbSJce6WgSaSm1+7xTpk9ZRr9ezFaABCreIUS6g=&code=AAABAAA…km1IgAA&grant_type=authorization_code&redirect_uri=https://localhost:8443/auth&resource=https://api.office.com/discovery/  

The client_id parameter should match the ID of your application as configured in Azure AD. The client_secret parameter should match one of the keys configured for your application in Azure AD. The code parameter contains the access code received from Azure AD. Because we are using the access code to obtain an access token, the grant_type parameter should be set to authorization_code. The redirect_uri parameter should be set to the same URL as the one used in the request for access code. Because we want to access the Discovery Service the resource parameter should be set to https://api.office.com/discovery/.

If the request was successful you will get a JSON response similar to the following:

{
    "token_type":"Bearer",
    "expires_in":"3599",
    "expires_on":"1431982776",
    "not_before":"1431978876",
    "resource":"https://api.office.com/discovery/",
    "access_token":"eyJ0e...wTn_qg",
    "refresh_token":"AAAB...wh8gAA",
    "scope":"AllSites.Read Sites.Search.All UserProfile.Read",
    "id_token":"eyJ0eXAiO...3B4In0.",
    "pwd_exp":"10729289",
    "pwd_url":"https://portal.microsoftonline.com/ChangePassword.aspx"
}

The response contains some information about the access token such as its validity period and the resource for which it has been issues as well as the access token itself. Additionally the scope property contains information about the different services to which the application has been granted access. The access_token property contains the access token that you should use to query the Discovery Service for available resources.

An access token is valid for a limited period of time (1 hour in Azure AD as defined by the number of seconds specified in the expires_in property) and needs to be refreshed on regular. While you could do that by starting the complete auth flow, an easier way is to use the refresh token provided in the refresh_token property. Comparing to the access token, the refresh token is valid for a longer period of time and allows you to get a new access token directly without retrieving the access code first. To provide a great user experience to your users you should store the refresh token in your application so that when the user is authenticated you can quickly authorize your application with Azure AD and get the data. The important part is that you should treat both the access token and the refresh token as passwords and should never store them on the client.

Currently the different Office 365 APIs are served from different URLs and they require different access tokens for you to connect to them. While you could perform the complete auth flow to retrieve an access token for the specific service, there is an easier way to get access to the different services in Office 365. As described in more detail by Vittorio Bertocci Azure AD uses Multi-Resource Refresh Tokens (MRRT). What that means is that you can use the same refresh token to obtain access tokens to the different services backed by Azure AD! This simplifies working with the different Office 365 APIs and improves the user experience of your application. When the new Office 365 Unified APIs will be released switching between the different endpoint to access the different services will not be necessary for most cases. Until then using using the refresh token to obtain access tokens for specific services can help you improve your application.

Querying the Discovery Service to get information about the available services

The next step is to query the Discovery Service to get information about the different services that your application is allowed to access. This is done by issuing a GET request to the following URL:

https://api.office.com/discovery/v1.0/me/services  

When issuing the request pass the previously obtained access token in the request headers:

Authorization: Bearer eyJ0e...wTn_qg  

If the request was successful you will get a response similar to the following:

{
    "@odata.context":"https://api.office.com/discovery/v1.0/me/$metadata#allServices",
    "value":[
        {
            "@odata.type":"#Microsoft.DiscoveryServices.ServiceInfo",
            "@odata.id":"https://api.office.com/discovery/v1.0/me/services([email protected]_SHAREPOINT')",
            "@odata.editLink":"services([email protected]_SHAREPOINT')",
            "capability":"MyFiles",
            "entityKey":"[email protected]_SHAREPOINT",
            "providerId":"72f988bf-86f1-41af-91ab-2d7cd011db47",
            "providerName":"Microsoft",
            "serviceAccountType":2,
            "serviceApiVersion":"v1.0",
            "serviceEndpointUri":"https://contoso-my.sharepoint.com/_api/v1.0/me",
            "serviceId":"O365_SHAREPOINT",
            "serviceName":"Office 365 SharePoint",
            "serviceResourceId":"https://contoso-my.sharepoint.com/"
        },
        {
            "@odata.type":"#Microsoft.DiscoveryServices.ServiceInfo",
            "@odata.id":"https://api.office.com/discovery/v1.0/me/services([email protected]_SHAREPOINT')",
            "@odata.editLink":"services([email protected]_SHAREPOINT')",
            "capability":"RootSite",
            "entityKey":"[email protected]_SHAREPOINT",
            "providerId":"72f988bf-86f1-41af-91ab-2d7cd011db47",
            "providerName":"Microsoft",
            "serviceAccountType":2,
            "serviceApiVersion":"v1.0",
            "serviceEndpointUri":"https://contoso.sharepoint.com/_api",
            "serviceId":"O365_SHAREPOINT",
            "serviceName":"Office 365 SharePoint",
            "serviceResourceId":"https://contoso.sharepoint.com/"
        }
    ]
}

The contents of the response will vary based on the services your application has access to. In the example above the application has access to user’s files and all files stored in SharePoint. Each Service Information object contains the serviceEndpointUri property which specifies the URL that should be used to communicate with the specific service. Before you do however, you need to obtain a valid access token for that particular service.

Obtaining an access token for SharePoint

The access token that we have obtained previously was valid only for the Discovery Service. If we tried to use that access token to communicate with SharePoint, the request would fail. In order to communicate with SharePoint, or any other service for that matter, you need an access token issued for that particular service. If you stored the refresh token as described previously, you can easily obtain a valid access token by issuing the following POST request:

https://login.microsoftonline.com/common/oauth2/token  

Pass the following parameters as x-www-form-urlencoded:

client_id=4f468d22-7e84-4a8c-af4e-747a450c0bc5&client_secret=oIa4kbSJce6WgSaSm1+7xTpk9ZRr9ezFaABCreIUS6g=&refresh_token=AAAB...wh8gAA&grant_type=refresh_token&redirect_uri=https://localhost:8443/auth&resource=https://contoso.sharepoint.com/  

Notice how the grant_type parameter is set to refresh_token and instead the code parameter we used initially, we’re using the refresh_token parameter. Additionally in the resource parameter we’re specifying the URL of the SharePoint site that we want to access.

If the request was successful you will get a response similar to the following:

{
    "token_type":"Bearer",
    "expires_in":"3599",
    "expires_on":"1431983294",
    "not_before":"1431979394",
    "resource":"https://contoso.sharepoint.com/",
    "access_token":"eyJ0e...KWitGw",
    "refresh_token":"AAA...P-IAA",
    "scope":"AllSites.Read Sites.Search.All",
    "pwd_exp":"10728771",
    "pwd_url":"https://portal.microsoftonline.com/ChangePassword.aspx"
}

Just as previously the response contains some information about the access token and the permissions it grants. This access token allows you specifically to access the SharePoint site specified in the resource parameter. As mentioned before refresh tokens issued by Azure AD are multi-resource and you can update the refresh token you have stored previously with the one you have just retrieved to extend the validity period of your refresh token.

Calling SharePoint

Now that we have a valid access token, we can call any of the standard SharePoint APIs passing the access token in the request headers. Following GET request for example would retrieve 10 documents from SharePoint using SharePoint Search:

https://contoso.sharepoint.com/_api/search/query?querytext='*'  

Headers:

Authorization: Bearer eyJ0e...KWitGw  

Similarly to the call above you could call any of the other APIs available in Office 365 passing the corresponding access token in the Authorization header.

Summary

To simplify building add-ins and web apps on Office 365 Microsoft released SDKs for the most popular platforms for communicating with Office 365 APIs. Even if the platform that you are developing on doesn’t have a dedicated SDK, you can still connect your application with Office 365. By completing the OAuth flow with Azure AD through a number of web requests you will authorize your application to interact with the different Office 365 APIs. And even if there is an Office 365 APIs SDK available for your platform it’s very helpful to understand the different steps in the OAuth flow in case things aren’t working as expected.

Comments

comments powered by Disqus