Creating an O365 Authorization Token via Chrome Extension

In this article I will show how I extended my method for generating an O365 OAuth token and incorporated it into a chrome extension.

Introduction

When I created the O365Token project on GitHub it was for the express purpose of being able to generate an OAuth token for an O365 Add-In project. I have since been tasked with integrating O365 into an application via a Chrome Extension. Using the same methodolgy it turned out to be relatively simple to do.

Creating a Chrome Extension

There is an extensive API for creating Chrome extensions which allows us to execute JavaScript at run time for a given website. What is particularly useful is that we are able to execute different scripts based on the site being accessed.

The basic extension

I created a extension locally with nothing more than the basic inclusion of a manifest and a JavaScript hello world.

g1

The background.js file is very simple

$(document).ready(function() {
    console.log('hello world');
})

and when I visit an https://xomino365.com site I see the extension log in the console.

g2

Adding O365Token to the extension

In the github project we have two files, Home.js and App.js. These two files are added to the chrome extension and the folder structure.

The Home.js file is modified with the necessary parameters for generating the OAuthToken as described in this previous article. I also modified the replyURL as in this case it is not an Office Add-In.

g3

You will also notice that I changed the first few lines of code to remove the call to Office.js.

Executing the Chrome extension

Once the code has been implemented, I go to a https://xomino365.com webpage and I am immediately prompted with a new window requesting O365 Authentication.

g4

g5

Once I authenticate, an OAuthToken is created and set as a cookie within the xomino365.com domain. Using this I can then add O365 application data into my xomino365.com website seamlessly.

I

Because of the ability to “match” the website which this occurs in, within my extension, this functionality will only appear on this website.

Updating the O365Token Github

I have updated the O365Token Github site with the Chrome extension as a separate folder within the repository. Please feel free to try it out for yourself with your own O365 sites.

 

Conclusion

In this article we have seen how a simple Chrome Extension is constructed and how we can add O365 Authorization capabilities to it.

The ability to easily integrate O365 through a Chrome Extension opens up the future possibility for integration between existing applications and O365 through the use of DOM insertion. More on this in a later article.

Corporate Tools to come…..

What is intriguing to me is that unless you’re using corporate GMail, Chrome itself is not normally a “default browser” inside a company using O365. More likely of interest to corporate world is that Microsoft Edge Extensions are coming (as of April 2016) and they are supposedly going to be very similar to Chrome extensions. This could very well have a lot more developer leverage in that environment. I guess I need to get on that train and find out……

 

 

Advertisements

Caching data in O365 Add-ins using document.cookie

In this article we will look at a technique for caching data (ultimately an OAuth token) within an Office Add-in.

Introduction

In previous articles I have discussed how to create an Authorization token in an Office Add-in and created the O365Token project on Github. These set up the possibility for using only JavaScript (no C#) to generate an Azure AD Authorization token which can then be used to interact with the O365 environment.

The only drawback so far is that every time the Add-In loads, a new window pops up to collect the token. It would be a much more elegant solution to be able to cache the token somehow and then re-use it. In this article we will look at using cookies for “caching” tokens in both the Outlook Client and the O365 web mail experience.

 

Cookies

Cookies have been around for almost as long as web browsers. They can be set to hold a value for a finite amount of time (permanent) or fixed to only this browser session (session).

Using the FireBug Lite technique previous described we are able to take a look at cookies and how they are stored within the browser.

Within Outlook itself we can see the cookies using document.cookie

c1

and we can set a cookie like this

c2

Setting an expire date

So that’s all well and good but if we actually want to store an OAuth token we want the cookie to be valid for no longer than the token itself. So then we have to set an expire date when we create the cookie. This is achieved like this:

function setCookie(value, duration) { 
  var now = new Date();
  var time = now.getTime();
  var expireTime = time + 1000*duration;
  now.setTime(expireTime);
  document.cookie = 'OAuthToken='+value+';expires='+now.toGMTString()+';path=/';
}

And in FireBug we can see this in action – in this case we set the cookie for 10 seconds, and immediately log it to the console

c3

and then more than 10 seconds later we just test the document.cookie and the OAuthToken is gone

c4

OAuth token generation

When requesting the OAuth token for O365, the token returned is valid for 3600 seconds (an hour). So if we cache the cookie for an hour it will be a good indication (by its existence) that it is still valid. If there is no cookie – we have to get a new token.

Conclusion

In this article we have seen how through the use of the browser’s cookies, we are able to potentially store data. In a future article we will look at how to store and reuse an OAuthToken

 

 

O365Token GitHub project – Authenticating Office Add-Ins to Azure AD using only JavaScript (No C#)

In this article I will discuss the first iteration of the new GitHub project I created for the O365Token generation. The project is a generic code sample which can be added to your Azure AD websites and ultimately used to create a secure sample Add-In. We will look at how to take the sample code in the GitHub repository and deploy it to your environment.

Introduction

In the previous article I showed an alternate method for creating an authorization token from within the Outlook client. After receiving encouragement from Simon Jaeger I decided to continue and make this into something to hopefully collaborate on with others.

Github O365Token

The repository is hosted here – https://github.com/markyroden/o365Token – clone it to wherever you want (I use Webstorm IDE) and follow these steps:

  1. Using the instructions posted here, create your Azure AD site and make the redirect URL match the sample/index.html path.
    e.g. https://yoursite.azurewebsites.net/sample/index.html
  2. Modify the following token parameters in app.js to match your application
    • clientid
    • resource
  3. Run

 

How it works

In this version of the token generation I combined a number of aspects of the code and streamlined them to work as one file. There only 3 files (not including CSS) involved in this O365Token sample.

o1

  • Index.html
    • The place holder for the Add-In
  • Home.js
    • Determines if the code has been opened in an Add-In or as a popup token generator
  • App.js
    • If the page opens as an Add-In it causes the pop-up token generation window
    • If the page has been opened in the add-in it acts as the recipient of the token generated in the popup

Combining code

To simplify deployment and maintenance over time I decided it was easier to write the token generation code into the add-in itself. This also helps to reduce the number of changes necessary

Index.html

Index.html is really just the placeholder for the sample code – all that happens is that it ends up displaying the token once it is generated.

Home.js

We are using the same /index.html as the Add-In and the popup token generation window as well. The Home.js file determines if index.html has been opened as an Add-In and if so, calls the app.getToken code. If index.html has been opened in the browser the app.returnToken is called.

o2

App.js

App.js has three functions:

  • app.getToken
    • Called when index.html as been opened in the Add-in
  • app.returnToken
    • Called when index.html has been opened in the popup
  • app.tokenCallback
    • Called from the app.return once a Token has been generated. This is where your actual Add-In code would live in the future.

o3

For the Future

I have a feeling that this ought to be an Angular module. I can see a lot of Add-In code being written as an Angular app and as such it would make sense to include the app.requestToken and app.getToken as something which can be hooked easily into any other angular app.

 

 

 

 

How the example O365 Authorized CORS application works.

In this article we will look into how the example provided on the Microsoft HowTo site works and then discuss some practical implementations thereof.

Introduction

In the previous article (https://xomino365.com/2016/02/01/using-azure-ad-to-allow-authorized-cors-access-to-o365-data/) we looked at how to create an Azure AD application and securely access O365 data from within another web domain. The Microsoft How to site provides and example application on how to get data from your One Drive. But in this case we are going to look at how to get data from a SharePoint site collection.

The basic site

The site does have a good working example, you can copy and paste the code. What I wanted to show here was the end result and how it works. I modified mine slightly to pull data from a SharePoint list rather than OneDrive but it all works.

Starting at the site root (which is anonymously accessible), we click the Get Token button.

a13

The application then makes a request to the Azure authentication pages


aa2

Combining the values added to the example application we get the following values added to the Query_String of the address. These values must coincide with the values in the application manifest.

client_id=xxxxxxxx-xxxx-xxxx-xxxx-dca7fd30e1cb
redirect_uri=https://xomino365.azurewebsites.net/o365/demo.html
resource=https://xomino.sharepoint.com
response_type=token

If the user is not signed in then they are asked to do soaa1

Once successful authentication has been achieved the login end point returns the user to the “redirect_uri” and tacks the OAuth token onto the end of the returned URL

aa3

The application also sets a cookie – this is the Authentication cookie which says that you are logged into O365 – but that is very different from the Authorization (OAuth) token which is currently in the URL. You will also note if you look carefully that there is an expiry time in the Query_String parameters (3599) so assuming this is in second and not minutes – the OAuth token is only good for 60 minutes….

The example application waits for the response and if it find an access_token in the URL it parses it, and then moves it into the OAuth Token field

aa4

In this example the Endpoint is a hard coded URL which represents the Root folder of the root site in my O365 site. It is an out of the box REST URL.

https://xomino.sharepoint.com/_api/web/lists/getByTitle(@TargetLibrary)/RootFolder/files?@TargetLibrary=’Documents’

If we pull that up in a new tab we get the following

aa5

The reason I am getting this is because I have not actually authenticated with xomino.sharepoint.com at this time – I have logged into Azure AD. This is really interesting because if I run the example right now it will work – AzureAD has given me enough permission to make the request but not to go directly to the site. I say interesting, but it is actually slightly annoying from a developers perspective. Every time a user moves around O365 they have to go through the Single Sign on process – which is very cool, in that it works, but not the ideal user experience.

If I open https://xomino.sharepoint.com in a new tab – I get the cycle login screen and my SharePoint sites open automagically – SSO works. When I go back to the REST endpoint again now I get an authorized page.

aa6

The only reason I even bring this up is to show that Authorization is not the same as authentication. The Access_Token actually grants us permission to retrieve data and interact with the SharePoint site, even though technically we are not logged into it (yet). Pretty smart to be honest!

But this is XML – old school ATOM service. – we want new school JSON and the example app obliges.

Getting JSON Data

When the demo site realizes there is an access_token in the URL it hides the GET TOKEN button and shows the Make CORS Request button.

Clicking the Make CORS request button creates a very specific AJAX request – let’s look at the code directly.

  var xhr = new XMLHttpRequest();
  xhr.open("GET", getEndpointUrl());
  xhr.setRequestHeader("authorization", "Bearer " + token);
  xhr.setRequestHeader("accept", "application/json");
  xhr.send();

In this case the token is the very long access_token from the URL and the getEndpointUrl() is the xomino.sharepoint value in the EndpointURL field.

Once the AJAX call is made you can see what happens in the transfer using the browser developer tools (in this case firebug). The Accept Header is what will cause the O365 server to respond with JSON and not ATOM XML.

The Request Headers

This is what is going out to the O365 servers – as you can see the Accept Header and the Authorization header have been set.

aa7

The Response Headers 

The critical thing to note here is that the Access-Control-Allow-Origin Header = “*” this allows the xomino365.azurewebsites.net domain to successfully request data from the xomino.sharepoint.com domain.

aa8

The response itself

The response is a JSON data object

aa9

making it more readable we can see the object is an array of “results” within d. Each item within the array represents the verbose detail of each file within the site collection.

aa10

Conclusion

 

In this article we have looked in some detail at how the Microsoft HowTo website example works and how the authorization/authentication mechanisms play with the AJAX requests to retrieve data from one domain into another.

In a future article we will look closer at what happens when we start to play with these requests and try and break the system…