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.

 

 

 

 

Advertisements

Simplifying O365 Outlook client Add-In Authorization without C#

In this article I will demonstrate a simple method for getting an Authorization into and Outlook Add-in without writing any C# code. I will also highlight some of the problems involved and how the solution elegantly overcomes this.

Introduction

In the previous article we looked at how the How the example O365 Authorized CORS application works and in that example is a location.href change which works just fine within a web browser, but fails badly as an outlook client Add-in.

When the example CORS application is packaged and deployed as a client Add-in it appears to work until you click the “Get Token Button”. The location.href change causes an Internet Explorer window to open, where you can log in……but the end result is you being in an Internet Explorer Window and the token is not in the Outlook Add-in.

A recognized way to solve this issue 

Simon Jaeger has written a number of excellent articles on how to create Outlook Add-ins through Visual Studio and writing some C#

http://simonjaeger.com/developing-outlook-add-ins-where-to-integrate-and-what-you-can-do/

http://simonjaeger.com/building-a-good-authentication-flow-in-an-office-add-in/

The guys in my team tell me that those are a pretty sweet solution to the problem, but my problem is I am not a C# developer and have no desire to become one.

What Simon’s code did do though, was was to inspire me to try something different.

Solving the problem without C#

As I understand it Simon’s example opens an authentication window and then passes the authentication token back to the Add-In via SignalR

 // Show prompt in a new window
    window.open(redirectUri.replace("signalrid", signalrId), "",
        "menubar=0,location=1,resizable=1,scrollbars=0,status=0,toolbar=0,width=550,height=600");

But it struck me that the window.open opens the possibility for the open window to communicate with the opener. (Yeah I know that’s a dumb sentence but it is accurate).

So I put it to the test. I created a button on my sample index.html and made the deployment as an add-in

c1

The code on the button – dead simple – open the window on itself (it really doesn’t matter which site)

<button onClick="window.open('https://xomino365.azurewebsites.net/o365/index.html')">Open Window</button>

Looking at the open window we can bring up developer tools and use the console to test if window.opener is null.

c3

and it isn’t.

So then let’s do a test – let’s see if we can manually stick a value back into the opener……and it did !!

c4

Well in that case we are all sorted !!

Modifying the example code

I am modifying my existing code for the sake of a consistent story, this is not how you would do it in production.

  • If the index.html opens and window.opener is not null I call the function to requestToken() automatically.
  • The page reloads
  • If the page loads detects that we have a token, and we have a window.opener, it
    • Sends the token back to the Outlook client Add-In
    • Hides all the buttons
    • Clicks the Make CORS Request button automatically
    • Closes the popped up window
            if (window.opener){
                window.opener.document.getElementById("TxtOauthToken").value = token;
                window.opener.document.getElementById("doCors").style.visibility = "visible";
                window.opener.document.getElementById("doCors").click()
                window.opener.document.getElementById("getToken").style.display = "none";
                window.close()
            }

And that’s it – the user either sees a quick popup and then the Add-In gets the data from SharePoint. If they have not checked the “keep me logged in” box, or have had their login expire, they see a log in screen where they authenticate with O365 SharePoint, the window then closes and runs in the Add-In.

c5

Conclusion

In this article we have seen how to use a window.open from within our Outlook Add-in to be able to create an Authorization token which can be passed back to the Add-In and used to get Cross-Domain SharePoint data from O365.

In a future article I will streamline this code to create something which can be used for just authorization and is not the same webpage as the Add-In.

 

PS

If you have never done this before you may be prompted with the following dialog – which MAY come up in the background as well. You need to (and tell your users to ) check the box and Allow this in the future.

c2

PPS

I also discovered that you can use WebSockets to transfer data “into” the Outlook Client Add-In. This turned out to be unnecessarily complex and raises some security concerns – but – makes for some excellent ideas for future Add-In functionality ideas.

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…

 

Using Azure AD to allow Authorized CORS Access to O365 data

In this article I will show how to to create an Authenticated way to access O365 data from an Azure website. This method creates the necessary CORS headers to allow cross domain AJAX data traffic.

This whole article is based on the following site Create JavaScript web apps using CORS to access Office 365 APIs. I wrote this article because it was not at all clear to me from the Microsoft posting how everything fit together and I had to go through it a number of times to figure it out.

The article and screenshots are accurate as of 31 Jan 2016 and may change over time.

Setting up Azure AD as your O365 directory

For a more in depth description of how to use Azure AD as your directory for O365 check out this excellent support article. This is also a very helpful link – What is Azure AD Directory? it will help you describe how to assign your Azure AD to your MS Cloud account.

Once you have the Azure AD directory set up you can manage it though the Azure portal. In there you can find your directory by scrolling to the bottom on the left and selecting Active Directory.

a1

 

Adding a new application

Select Application at the top of the screen and select Add at the bottom

a2

Add an application my organization is using

a3

Give it a name

a4

Give it a sign in URL and and APP ID URI (“The App ID URI is a unique identifier for Azure AD to identify your app“)

a5

For the sake of this demo the above values are arbitrary and make more sense in context of the overall configuration.

a6

woo!

Select Configure at the top and look at what was created

App configuration

The configuration section shows all the information you need, and you application needs to be able to access O365 data from your application. This does NOT have to be an azure hosted application. I am just using Azure for the sake of convenience.

The name and Sign-on URL are carried over – the Sign in URL is actually merely for convenience, you don’t need to use it as far as I can tell.

a7

The Client ID – this is the single most important piece of this puzzle – this key holds the application together. You send it as part of the request for Authorization token. With it O365 determines the what who why when for security.

a8

In the Single Sign on section below we see the App ID and the Reply URL (which is the Login page URL)

a9

We are going to change the reply URL to be the App ID for convenience. Don’t forget to save!

a10

We have to give the demo.html application access permissions inside of O365

Adding permissions to applications

Selecting Add Application brings up all the applications being managed by Azure AD directory.

a11

We are going to change permissions to access SharePoint online. Select and continue..

Select the delegation permissions. In this case I blanket added all permissions just for the sake of not having to explain everything. You probably want to make sure that you understand what permissions you are exactly giving the user. Remember once you create the authorization, users can write their own JavaScript and do not have to do what you want them to, they can do what you authorize them to do.

a12

and don’t forget to save…..remember this, otherwise you will waste time wondering why you are an idiot….

Changing the manifest

The manifest file is available at the bottom of the screen – selecting the link will download the text file.

a15

Looking at the manifest we see the true textual representation of the configuration. The important part here is to allow the application to allow the OAuth token to be returned to the user so it can then be used for further data requests. If you do not make the following change the example application (see below) will return the following…

error=unsupported_response_type&error_description=AADSTS70005:+response_type+’token’+is+not+enabled+for+the+application
Trace+ID:+f4354ef3-de41-4909-a829-0811b0bc0407
Correlation+ID:+93f60ed1-f703-4b5d-b0fb-bebc94192f3b
Timestamp:+2016-01-31+03:36:57Z”

To correct fo this issue, change the following line to true

“oauth2AllowImplicitFlow”: true,

Save the manifest and upload it again.

Creating an application

Following the methodology from the previous article, I created an Azure HTMl5 app with source control integration and loaded the example files up to the demo.html page.

The demo Application

The end product looks like this.

a16

Click the button to get the OAuth Tokena17

The Token is returned as part of the URLa18

Clicking the CORS Request button collects data from the default site collection on the https://xomino.sharepoint.com O365 account.

We do not need to make this a 2 step process though, in later article we will show how to create the results in the form of an angular ui-grid

a19

Conclusion

It is a little convoluted to create and set up an “Application your company is working on” and make it use O365 Authorization and Authentication. But once you go through it the first time it becomes relatively east to remember.

We were able to request O365 data on https://xomino.sharepoint.com from a site not in the same web domain, https://xomino365.azurewebsites.net

This is the first example and I will be writing more about how it all fits together in the future.

 

 

 

 

 

 

 

 

 

 

Securing your Azure HTML5 Web App

In this article we will look at the simple procedure for enabling authentication on your static HTML5 website.

Introduction 

In the previous article we looked at how to set up an HTML5 website in Azure. This left the files open to anonymous access. In this article we will look at the simple steps within the azure portal to secure the site with your O365 credentials.

Azure portal admin

From our azure portal homepage (https://portal.azure.com/) select Web Apps

q1

Clicking on the Web App bring up multiple options and setting

q2

Under settings select Authentication / Authorization

q3

And then turn it on

q4

Save – and that’s it – your site is now secured to the Active Directory users provided by your O365 and Azure cloud.

Accessing the home page now brings up the login screen

q5

Conclusion

We have seen how to secure the open Azure site to external users. In the case of the Outlook Add-ins we are trying to create this will leave them accessible to authenticated users.

 

Setting up an Azure HTML 5 web app with source control integration

In this article I will show to create an HTML 5 Web App in Azurefrom a template repository. We will then modify the repo and push out first files back into Azure.

Introduction

In previous articles 1, 2, 3, 4 I have been showing how to use napa development tools to create. In this article I will demonstrate how to create a basic Azure app which will host our files for us.

Azure Web App

From your Azure portal you can create a new web app

z1

In this case we will create xomino.azurewebsites.net. As we are doing nothing more than hosting files right now, we will create it as an empty HTML5 container.

Select to cfreate a web app from existing gallery

a1

Find HTML5 Empty Web App

b1

Moving to stage two give it a name and create

b2

Once the app is created you can then add your files to it a number of ways – my personal preference is to deploy from a git repo.

Web App Dashboard

When you click on the new link you will see the web app dashboard

e1 e2

From there we can set up Integration with Source Control

Hooking Azure up to the local repo

When you select connect to local repo the first time you will be prompted to create a username and password. This is so that you can FTP your files up to azure.

z8

Once that is created you will be presented with a screen to integrate your Git solution (manual or otherwise) with Azure.

b1

I use Webstorm for my development, so used the git tools in there to clone the repo down from Azure

There is nothing more than and HTML file and a favicon…

e3

I then:

  • messed a little with index.html
  • added my Files from the add-in
  • committed them all
  • pushed them back up to azure.

e8

Immediately the azure dashboard updates with a deployment message – once the deployment is complete (which is seconds fast) you will see an arrow top right. Clicking on it shows you the deployment process (3 seconds)

e4

The website is now available. Clicking back on the dashboard we now see activity. Over on the right we can click to open the Azure portal Dashboard for this web appe5

Opening up the website (http://xomino.azurewebsites.net/) we can see the index.html page I messed with

e6

 

And if we navigate to the Add in file folder it exists, but doesn’t do anything (yet)

e7

Conclusion

In this article we have seen how to:

  • Create our first Azure HTML Web App
  • Attach the app to source control locally
  • Add our Outlook Add-in files,
  • Commit and push back to Azure
  • Open the files directly in Azure

The hosting of the Outlook files is crucial for them to be made available to a wider Exchange audience in the future.

NOTE

There is no security associated with this site – it is wide open to Anonymous users. That is probably good in the long term for an Add-in