Smarter ideas worth writing about.

Access Microsoft's Outlook API Using the OAuth2 Implicit Flow

I was recently tasked with creating a Webpart for displaying a user’s Outlook calendar events using the new Microsoft Outlook API endpoints, which requires passing an authorization token in the header of any request in order to gain access to a user’s Outlook data. Before people flee in terror at the prospect of dealing with Sharepoint, let me assure you this guide has very little to do with Sharepoint (I know very little about Sharepoint and how it all works, myself). This post is a step-by-step of how I accomplished connecting to the Outlook API.

OAuth2 has several different “flows” that handle different scenarios. There’s the Authorization Code flow, Implicit Grant flow, Resource Owner Password flow, and the Client Credentials flow. The latter two flows are only used in very specific situations so I won’t go into those here. The most commonly used are the first two. The Authorization Code flow requires server side code and makes multiple requests, the first to get a code that is then used to obtain an authorization token from the authorization server in a second request. The Implicit Grant flow is executed entirely from client side code (javascript more than likely) and only uses one request made to the authorization server to obtain an authorization token. As you can see from the diagram below, there is a lot going on when that one request is made, however:

The first step for getting the data we need is constructing a call to the Microsoft OAuth2 authorization endpoint. There are five total parameters, though not all are required. They are as follows:

Client ID - obtained when registering the application with Microsoft’s Application Registration Portal. This identifies to the authorization server that this application is recognized as being able to make requests for tokens. After registering the app you’ll need to make sure to add a Web Platform entry, add your redirect URL, and make sure the “Allow Implicit Flow” checkbox is checked:


Redirect URI – this tells the authorization server where to send the token back to. This is where we will extract the token from the hash fragment. In our case we are simply redirecting back to our home page, the same page from which we made the initial request from. This is not a required parameter per the OAuth2 specification, but it is commonly used.


Response Type
– this parameter tells the authorization server what it should respond with (and effectively determines which OAuth2 flow we are using.) In our case, this is set to “token”, telling the authorization server it will be returning an authorization token. If we were using the Authorization Code flow, for example, the response type would be “code”.

Scope – this is another optional parameter that tells the authorization server the scope of what we need to be able to do with our subsequent request. In our case, we’re using the “https://outlook.office.com/Calendars.Read” scope to tell the authorization server we’re only interested in being able to read a user’s Outlook calendar data. If this parameter is not specified, the authorization server should have a default scope it uses.


State
– this is a security related parameter that can be added to the request to make it easier to verify that the response is coming from the authorization server and not another source with ill intent. The idea is to create a string that would be very difficult to mimic (some suggestions I found were to use a hash of the session id, or current date time, or both) and then send this with the request. The authorization server should then send back the exact same string when it returns the authorization token. If not, then the call was hijacked and the response can’t be trusted.

Here is the complete example (the state parameter is stored in a cookie so after the redirect it can be retrieved to compare with the state parameter returned):


var clientId = "356c9774-a1f2-44g0-a873-f8az9de78657";
var redirectUrl = http://localhost:61090/”
var authServer = https://login.microsoftonline.com/common/oauth2/v2.0/authorize?”;
var responseType = "token";
var stateParam = Math.random() * new Date().getTime();
document.cookie = "myEventsState=" + stateParam;

var authUrl = authServer +
              "response_type=" + encodeURI(responseType) +
              "&client_id=" + encodeURI(clientId) +
              "&scope=" + encodeURI("https://outlook.office.com/Calendars.Read") +
              "&redirect_uri=" + encodeURI(replyUrl) +
              "&state=" + stateParam;

window.location = authUrl;

After making this call, the user will be presented with the standard Microsoft authorization page, where they will choose the account they want to authorize the Outlook API for and will be informed of the scope of the request (this is your typical “the application has requested permission to access your calendar” message). Then they will be redirected back to the home page, with a few new parameters in the hash fragment.

Here’s an example of the request url: 

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=token&client_id=356c9774-a1f2-44g0-a873-f8az9de78657&scope=https://outlook.office.com/Calendars.Read&
redirect_uri=http://localhost:61090/&state=401441800319.273

Here’s an example of the url after the redirect (I trimmed the token for brevity):

http://localhost:61090/
#access_token=eyJ0eXAiOiJKV1Qi.eyJhdWQiOiJodHRwczovL291dGxvb2sub2ZEu
MCJ9.jdIR9ia_1lth7VVgt2E3GqKkZrB5GIfkz_8CpgV3H_g&token
_type=Bearer&expires_in=3599&scope=https%3a%2f%2foutlook.office.com%
2fcalendars.read&state=401441800319.273

You’ll notice the state parameter is identical between the two URLs, which indicates the response is safe.

At this point we can choose to store this token in a cookie so the user won’t have to continue to grant access each time they navigate to the page. One of the ways the implicit flow differs from others is there are no refresh tokens granted, which allows the refreshing of access tokens without having to go through the authorization process again. With the implicit flow, once the access token has expired that’s it, you would need to start the process over to get re-authorized. We store the token in a cookie with the same expiration as the token so if the user logs back in within that time period they won’t have to re-authorize. Here’s a snippet of code to demonstrate:


var token = getHashParameterByName("access_token");
var expiresIn = getHashParameterByName("expires_in");
var returnedState = getHashParameterByName("state");
var stateToMatch = getBrowserCookie("myEventsState"); //state parameter cookie
if (token && stateToMatch && (stateToMatch == returnedState)) {
    var cookie = token;
    if (expiresIn) {
        var now = new Date();
        var hourLater = new Date(now.getTime() + (expiresIn * 1000));
        cookie = token + ";expires=" + hourLater.toUTCString();
    }
    document.cookie = "myEventsCookie=" + cookie;
}

Next, we make the call to the Outlook API endpoint with our authorization token. In this specific instance, we are calling the “calendarview” endpoint to retrieve Outlook calendar events for the given user. This requires a start datetime and an end datetime in UTC format, as well as a limit to the number of events retrieved (Using the $top query option from OData). Then we make a simple AJAX call with our authorization token in the header:


var startDateTime = moment().startOf("day").format("YYYY-MM-DD HH:mm Z");
var endDateTime = moment().endOf("day").format("YYYY-MM-DD HH:mm Z");
var apiUrl = "https://outlook.office.com/api/v2.0/me/calendarview?startdatetime=" + startDateTime + "&enddatetime=" + endDateTime + "&$top=" + 10;

$.ajax({
    type: 'GET',
    url: apiUrl,
    headers: {
        "Authorization": "Bearer " + token
    }
}).done(function (data) {
    processResults(data); //parses the json into objects used for display
}).fail(function (response) {
    $("#myevents").html("<span>Could not retrieve events</span>");
});

This will return a response that, if successful, will contain JSON representing all of today’s events from the user’s Outlook Calendar.

You can play around with the API at https://oauthplay.azurewebsites.net by logging in with any Microsoft account.

If you need to make a call to an OAuth2 protected endpoint from client-side code, the implicit flow is the way to go. It’s pretty straightforward once you understand the parameters required in your request, and how to extract what you need from the response. Once you obtain that authorization token, getting the data you need is as simple as adding an HTTP header and firing away.


Share:

About The Author

App Dev Consultant

Jonathan is a Senior Consultant at Cardinal’s Cincinnati office. His primary experience is developing .NET MVC applications, but he is always eager to branch out into new areas. Recently he received his MCSD certification, and has been experimenting with Azure solutions. He also loves Agile development and getting others to love it too.