Using OAuth2 to access Calendar, Contact and Mail API in Office 365 Exchange Online

I am excited to announce that finally EWS in Exchange Online as part of Office 365 exposes a RESTful API for Calendar, Contact and Mail that uses OAuth2 for authorization. In this blog I want to briefly describe Exchange's underlying OAuth2 implementation and how to use OAuth2 to access the new Calendar, Contact and Mail APIs.

First and foremost Office 365 fully integrates with Microsoft Azure Active Directory (AAD) to implement the OAuth2 protocol. There is an exciting announcement available here from Alex Simons, Director of AAD that outlines the new AAD capabilities around this protocol. At the end of this blog I will refer to more documentation. Don't hesitate to ask questions on Stack Overflow about accessing the new APIs using the OAuth2 protocol or about the APIs themselves. Please tag your question with [ms-office] and [ews] to get the fastest response possible.

I will focus in this post on the basic concepts and will highlight some of the differences compared to other OAuth2 implementations to get you started as fast as possible. 

Step One: Registering your application

Before you can use OAuth2 to access the Calendar, Contact and Mail APIs, your application needs to be registered in AAD. When you sign up for Office 365 for business or Office 365 developer, don’t worry, you already get AAD. If you are using Visual Studio, the app registration and permission management in AAD is done automatically for you! Outside of Visual Studio, you should visit the Microsoft Azure Portal and do the application registration there. For a step by step walkthrough, go here. During the application registration process a client ID for your application is created, client secrets for web apps are managed, and the permissions your application needs for accessing the APIs are defined.

Important:   Permissions must be defined up-front in AAD for the APIs as part of the registration process. While you might be used to specifying the permissions with the authorization request in other OAuth2 implementations by using the "scope" parameter, this is not possible at this point. In order for your application to configure these permissions in AAD, the AAD tenant where your application is registered must be linked to an Office 365 subscription with Exchange Online.

Step Two: Triggering user consent (aka authorization)

The goal of your application is to access the Calendar, Contact and Mail APIs. For this you need to get an access token that is passed along with the API request to Office 365. An OAuth2 authorization request is the first step for your application to get an access token. As part of the authorization process, user consent is involved. User consent is the act of displaying a dialog that clearly lists the permissions that your application is requesting. The user can decide if the permissions your application is requesting should be granted. The permissions that appear in this consent dialog are the same permissions you configured in Step One in AAD.

A typical authorization request looks like this (make sure you use https):

GET https://login.windows.net/common/oauth2/authorize?response_type=code&client_id=acb81092-056e-41d6-a553-36c5bd1d4a72&redirect_uri=https://mycoolwebapp.azurewebsites.net&resource=https:%2f%2foutlook.office365.com%2f&state=5fdfd60b-8457-4536-b20f-fcb658d19458

 

Parameter

Description

response_type

Required. Value is always code

client_id

Required. Value of your client_Id given when you registered your application with AAD

resource

Required. The Office 365 resource your app wants to access. As you want to access Office 365 Calendar, Contact, and Mail APIs this is "https://outlook.office365.com/".

state

Required. A long unique string value of your choice that is hard to guess. Used to prevent CSRF. For example, this can be a Guid generated by your app with each authorization request.

redirect_uri

Required. URI in your app where users will be sent after authorization. Must be registered in AAD.

Important: Redirect URIs must be registered in AAD as "Reply URLs" as part of the initial app registration, or at any point in time later in the process of developing your app. Failure to specify the correct redirect_uri will cause the authorization request to fail. So check your Reply URLs in AAD with your app registration.

If the user authorizes your application they will be redirected to the redirect_uri that you specified in your request above along with a temporary authorization code and the same state that you passed in the request above.

Upon successful authorization, the redirected URL should look like:

{your redirect uri}/?code={authorization code issued by AAD}&state={same state Guid passed as in the authorize request}

Ensure that the state parameter in this response matches the one you passed in the authorization request above. If the state does not match, that means the request may be a result of CSRF and must be rejected. 

If the user does not allow authorization to your application, redirection to the redirect_uri still occurs. Additional query parameters indicate the user canceled authorization and a short description of the error: 

{your redirect uri}/?error=access_denied&error_description=AADSTS65004%3a+The+resource+owner+or+authorization+server+denied+the+request.%0d&state={same state Guid passed as in the authorize request}

Before we continue with the next step on how to trade in the authorization code to an actual access token that you can use to access the Office 365 Calendar, Contact and Mail APIs we need to talk about a very nice variation of authorization you can request for a web application. Note that following doesn't apply for a native application. In particular AAD offers for a web application the capability for an administrator of an Office 365 Organization to consent on-behalf of all users in this organization. Once an administrator does this, users will not see any additional consent dialog with authorization requests. Essentially what this provides you is that your web application can have a sign-up experience for an organization in addition to an individual sign-up for a user.

You can accomplish this kind of organization sign-up in your app by simply modifying the authorize request to add an additional parameter called "prompt". For the example above this would be:

GET https://login.windows.net/common/oauth2/authorize?response_type=code&client_id=acb81092-056e-41d6-a553-36c5bd1d4a72&redirect_uri=https://mycoolwebapp.azurewebsites.net&resource=https:%2f%2foutlook.office365.com%2f&state=5fdfd60b-8457-4536-b20f-fcb658d19458&prompt=admin_consent

Triggering admin consent for an organization sign-up:

Parameter

Description

prompt

Value: "admin_consent". Indicates that the authorization request is for all users in an Office 365 Organization.

Important: Only an administrator of an Office 365 Organization can consent to such an authorization request. If an end-user tries to do this, AAD will redirect back to your application with an specific error indicating that consent could not be given.

Step Three: Trade-In for an access/refresh token

We're almost there. At this point we have an authorization code from a user or an administrator dependent on the authorization request your application sent. This code can be used to request an access token. Together with the access token your application will also receive a refresh token and an ID token. For the API access only the access token is important. The refresh token is for your app to keep in a safe place in an encrypted persistent temporary or permanent storage dependent on your app's requirements. You use the refresh token to request additional access tokens for either the same Calendar, Contact and Mail APIs or other Office 365 APIs such as OneDrive Pro. The ID token can be used to authenticate the user to your application. It contains the users ID and the organizations ID as known by AAD. You can use those IDs for your app's own memory or profile store on who signed up. Both access token and refresh token are JSON encoded web tokens that can be easily parsed. The specific properties to use for building an app-specific profile store in the ID token are "oid" for the user identifier and "tid" for the organization identifier.

Let's look at how such a token request looks like using the code.

Code Request:

The base token URL is:

POST https://login.windows.net/common/oauth2/token

The body is form encoded:

grant_type=authorization_code&code={code from the authorize request}&redirect_uri={reply url for your application}&client_id={your application's client id in AAD}&client_secret={your application's client secret}

Important : The redirect_uri in the token request must be the same as the one used with the original authorize request.

A successful response to this request contains the following fields in a JSON object:

Field

Description

access_token

Base64 url encoded JSON web token for API access.

token_type

Always "Bearer"

expires_in

The time period (in seconds) after which the access token will become invalid. For now this value is 60 minutes.

expires_on

Time in Unix epoch when the access token expires.

resource

The Office 365 resource or API that this access token applies to.

refresh_token

Opaque refresh token for your app to keep and get additional access tokens.

scope

The permissions that this access token contains.

id_token

Base64 url encoded JSON web token for user identification by the client application.

After 60 minutes the access token becomes invalid. A good pattern to follow is to cache this access token and use it to call the Calendar, Contact and Mail APIs until the API returns a 401 access denied with an error code of "invalid_token". In that 401 event your app should use the refresh token to get a new access token and retry the request.

Note: In case you are curious about what an access token or ID Token look like, there is a great web app available at https://jwt.calebb.net that allows you to simply cut and paste the token received from a token request and peek into the fields.

Request additional access tokens with a refresh token

Below is the request your app uses to get a new access token. The actual response is the same as in the code request, thus together with the access token your app receives a new refresh token. You should take the new refresh token to replace the old one as refresh tokens will expire in some period of time too.

The base token URL is:

 POST https://login.windows.net/common/oauth2/token

 The body is form encoded:

 

grant_type=refresh_token&refresh_token={the current RefreshToken in your applications cache}&client_id={your application's client id in AAD}&client_secret={your application's client secret}&resource={Uri of the API}

 

Important: The resource parameter indicates what API endpoint your application wants access to within the Office 365 APIs. For the Calendar, Contact and Mail API this is "https://outlook.office365.com".

As briefly mentioned above, the refresh token, while long living, becomes invalid at some point too. One example is if the user changes their password, refresh tokens become invalid. Your app can react to this gracefully by handling an error response from the token request that returns "invalid_grant". If this happens your app should go back to the authorization request as outlined in Step One to get a new authorization code and use this to get a new access token/refresh token pair.

 

Step Four: Accessing the API with the access token

We are almost there. Your application has an access token at this point for the Calendar, Contact and Mail API. Using this access token is fairly simple. When sending a RESTful API https request the access token is attached in the standard authorization header with the Bearer auth scheme. An example is listed below: 

GET https://outlook.office365.com/api/v1.0/me/folders/inbox/messages?$top=10

User-Agent: My-Cool-WebApp/1.0client-request-id: 9aa1c740-25e2-4841-9146-ef7018f7bf37return-client-request-id: trueauthorization: Bearer {access token your app received in Step Three}

Important: Always use https with your API request.

Unrelated to OAuth2, there are three http request headers the Office365 APIs would want your application to specify. This is the "User-Agent" the "client-request-id" and "Date". For User Agent you can follow RFC 2616 which basically describes it as {ProductName}/{ProductVersion} [{comment}]. For "client-request-id" your app should create a new Guid for each request. When the request fails "return-client-request-id" returns the Guid that was submitted as "client-request-id" with the request. It is highly recommended that you persist the failed request together with client-request-id and all http response headers in some application log. The "Date" requst header signals the date and time that the message was sent. It should follow the "HTTP-date" format as defined by RFC 2616)}. If you ever need help troubleshooting your application with the Office 365 APIs, this will be pave the route to a fast and successful resolution of the problem.

 

Client libraries are your Friend - use them!

Above I described how your application can apply the OAuth2 protocol for Office 365 APIs on the example of the Calendar, Contact and Mail API. While the OAuth2 protocol is a fairly straight forward and well understood pattern there are many things such as caching of access tokens/refresh tokens that are more complicated to handle within an application. The Azure Active Directory Authentication Library (ADAL) will help you abstracting not only the OAuth2 protocol, but also provide caching and mechanisms to get new access tokens. Whenever possible you should use this client library for your web or native app. ADAL comes for a variety of platforms including .NET, Windows Store, iOS and Android. Check them out!

Summary

Hopefully this blog provided you with enough detail to get started developing an exciting application for the Calendar, Contact and Mail API in Office 365. We would love to hear from you at this forum and are eager to know about your apps and feedback on how we can improve on our APIs and authentication to them.

Note that there will be many more functionalities coming in the next month and I will try to keep the blog updated whenever a new capability lights up. For example, the current blog describes the OAuth2 code flow, and AAD in the near future will provide a OAuth2 implicit flow that is optimized for JavaScript-based applications such as Office 365 mail apps. For sure we will post about this pretty soon. We are also working on having OpenID Connect available for single sign-on into your web app and Office 365. All more exciting functionality that will make application development more easy and hopefully worry-free regards the way your application authenticates with Office 365 APIs.

Additional documentation of interest

Finally, as promised, some pointers to documentation. Lots of time went into these and they are well worth reading while sipping your morning or afternoon coffee:

OAuth Sandbox: https://oauthplay.azurewebsites.net/

API Sandbox: https://apisandbox.msdn.microsoft.com/

Platform Overview: https://msdn.microsoft.com/en-us/office/office365/howto/platform-development-overview

Apps for Office: https://msdn.microsoft.com/en-us/library/office/fp161507(v=office.15).aspx

Office on Github: https://github.com/OfficeDev

OAuth2 Authorization Grant: https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx

OAuth2 client libraries: https://msdn.microsoft.com/en-us/library/azure/dn151135.aspx

AAD on GitHub: https://github.com/AzureADSamples