in Office 365, Office 365 API

Using an OAuth Controller to Authenticate and Consume Office 365 APIs

The samples and blog posts I have published on building ASP.Net MVC web applications that consume Office 365 APIs have used the OWIN Katana middleware for authentication. This directly integrates with the ASP.Net authentication pipeline and provides single sign-on for web applications.

The approach mentioned above is great if you only target Azure Active Directory (Azure AD) as the only authentication endpoint. This means, your application will only allow users to sign in with Office 365 credentials. This model works well for Line of Business (LOB) applications.

However, if your application integrates with its own authentication provider and still want to associate users with their Office 365 account to integrate users’ mailbox or query users’ OneDrive files, then the approach above wouldn’t make sense.

Building Your Own OAuth Controller

In such cases, you can build your own controller that will handle and process the authentication to Azure AD.

The GitHub sample – O365-WebApp-OAuthController – demonstrates exactly that.

The sample with its own way of signing in users adds the ability to call Office 365 APIs. This sample uses the OAuth 2.0 authorization code grant with confidential client and the Active Directory Authentication Library (ADAL) to obtain access tokens for the web app to call the Office 365 APIs with the user’s identity.

Quick Look at the OAuth Controller

The file you are looking for is: OAuthController.cs

The web application, without this OAuth controller is a result of: File->New Project->ASP.Net MVC Application with the default authentication options, which is configured to use Individual User Accounts.

New MVC Web App

I then added the code to query users’ OneDrive files which also involved me writing the OAuth authentication code.

The authentication flow is as follows:

Refer to my blog post – Office 365 APIs – RAW Version – to see the authentication flow and constructing the URLs as it will help you a lot in understanding how this thing works.

  • Construct the Authorization URL by specifying the OAuth controller URI as the redirect Uri
  • Try to acquire token  for Office 365 discovery service
  • Acquiring a token for the first time, without signing in will fail
  • User signs in to Office 365 and consents the web app
  • Once consented successfully, Azure AD will return the authentication result details along with an authorization code to the specified OAuth controller
  • Now, with this authorization code, you can fetch an access token for the discovery service (or any other services your application had requested permissions for)
  • Once you have acquired the token, you can redirect to where the request was initiated
  • Now you can query discovery service to get the Files endpoint and resource Id and then query users’ files

The OAuth controller’s Index action specifies the arguments that are returned from the Azure AD login endpoint:

public ActionResult Index(string code, string error, string error_description, string resource, string state)
{
 string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;
.....
.....

The parameter code corresponds to the authorization code received.

Using a State Parameter

One of the things we do in the sample is append a parameter called state to the authentication request.

It contains the details such as where to redirect (origin of the request) once the authentication action is completed successfully. To mitigate any cross-site request forgery, the web application  also generates a random Guid value along with redirect Uri.

This state value will be validated by the OAuth controller and redirection after login.

Feel free to clone or fork the project and let us know what you think!

Feel free to leave a comment below if you have any questions!

If you have a product/feature request, make sure you post your idea here!

Happy Coding!

 

 

Write a Comment

Comment

Time limit is exhausted. Please reload the CAPTCHA.