Posted by on Nov 20, 2015 in #Office365Dev | 4 comments

In Outlook add-ins, we have access to a great functionality within the APIs to get an identity token. This identity token represents the Exchange user and is key when it comes to building a single sign-on experience for your users.

If you would like to learn more about what’s inside the identity token – head to: http://simonjaeger.com/dissecting-and-validating-the-exchange-identity-token/

Why would you want to do this? Imagine if your add-in could sign in the user as soon as the add-in starts in Outlook – without having to ask for credentials every time. Not only is this behavior annoying from a user standpoint, but it’s also possible to overcome this because we have access to the identity token.

All you have to do in your JavaScript is to call the getUserIdentityTokenAsync function like this:

Next up you will need to send this token to your web service and validate it. There are many ways to achieve this, I will use the Exchange Web Services Managed API NuGet package (https://www.nuget.org/packages/Microsoft.Exchange.WebServices/) in this post for simplicity (no need to reinvent the wheel here!).

If you would like to get an overview of how to validate the identity token and pick out the pieces you need without any libraries – check this out: http://simonjaeger.com/dissecting-and-validating-the-exchange-identity-token/

Setting up

I’ll be building an ASP.NET Web API to handle my API calls from the Office add-in (also avoiding CORS hassles by hosting it alongside the Outlook add-in).

To deal with requests and responses I created the following classes to help me out:

The UserModel represents a user context in your own web service.

The CredentialsModel represents your own authentication implementations. It will be passed with a UserRequestModel when mapping a user in your own service with an Exchange user.

The UserRequestModel represents the request data that will be sent to the Web API controller when asking for user data (with the identity token).

Finally, I implemented the following interface – which calls back to my own backend to get users with a unique user identifier (created by the validated identity token).

Making the API method

Now let’s implement the ASP.NET Web API Controller to do all the magic! We will start out like this and then add more down below. I simply created an instance of the backend (IWebService) and accept the UserRequestModel as the parameter for the POST method.

Before finishing the POST method – we need to create a helper method for hashing. We will combine an input with a salt and return hash (SHA256) string based of that. I defined it like so:

Let me explain why we are doing this – and not just using the plain identifier from the identity token… When creating a unique identifier for the Exchange user, to map with a user in your own service – best practice is to create a hashed unique user identifier (by combining the authentication metadata document with the Exchange ID and a unique salt – read more at https://msdn.microsoft.com/EN-US/library/office/fp179819.aspx). Using the plain Exchange identity may expose your mapping to vulnerabilities.

Now we are ready to finalize the POST method!

Make sure to install the Exchange Web Services Managed API library… If you are using the Package Manager Console in Visual Studio – run: Install-Package Microsoft.Exchange.WebServices

The key to create a single and reusable API method here to allow for credentials to be optionally passed with the request. You can call the API method with an identity token, which gets validated and then looks for a user mapping with the GetUserAsync method. If there isn’t a mapping available, it will be created if credentials are present in the request – and then the user will be returned.

One thing is important to note here – we never do anything before we trust the identity token. So make sure to validate the integrity of the token before looking for or creating any user mappings.

Wrapping up

Back in the Outlook add-in, we can start getting the identity token and calling the API method right away to see if there is a user mapped already (upon launch). We can do this as soon as the Office.initialize function has been called by the Office.js library.

I created the following function to help me out with this:

I will use it when trying to get user data as soon as the Outlook add-in launches (SSO). But I will also use it when the user signs into my service for the first time – and do the user mapping. The only difference between the two calls is that I’m passing the credentials with the request when I want to map the Exchange user with a user in my backend.

Disclaimer: This is merely a demonstration of the authenticateAsync method. Make sure that your usage of credentials meets the security requirements of your application. You could either implement a token flow (i.e. using one-time tokens or the OAuth protocol) for your web service or POST directly over HTTPS (with an HTML FORM) to your API.

 

Ideally your web service should generate a set of (short-lived) credentials only intended for the user mapping. Validate and expire those credentials in your API.

And… voila! With that you can securely map users between the world of Office 365 and your own – to create a good single sign-on experience.

If you would like another reference for doing this, there’s a post available on MSDN that also covers the topic: https://msdn.microsoft.com/en-us/library/office/jj730476.aspx

Happy coding!

-Simon Jaeger