Touchpoints: Safe, Secure Integrations Everywhere!

Originally published June 15, 2017

The MindTouch Engineering team, as usual, has been hard at work. Between our recent updates to MindTouch site analysis tools and our efforts to optimize our cloud infrastructure, its been a busy first half of 2017. Our latest efforts have focused on one of our favorite features — Touchpoints. This is part one of a three-part series that will explore our development process, and the technologies we use to make Touchpoints secure, flexible, and incredibly simple to implement. This release culminates the hard work and thought leadership of many MindTouch software engineers — Aaron Mars and I led the architectural discovery and implementation, and David Crean led the second milestone to add customization and branding properties to the integration platform.

So what are Touchpoints? Technically, they are integrations, but they are so simple to use that we hesitate to refer to them that way. When you hear the word integration, you might feel the early twinge of an oncoming headache. We do, too. That’s why we’ve designed Touchpoints to make it extremely easy to embed MindTouch-powered features into any web application, including authoritative content, MindTouch site sign in, or dashboards that show MindTouch site usage. With some basic configuration, and the copy and paste of a small code snippet — one can have a working MindTouch integration in under a minute.

And Touchpoints are reactive — they can respond to DOM events in a webpage or even messages sent by other Touchpoints. For example, a Search Touchpoint can listen for changes in the Zendesk agent user interface, and query for solutions to a support ticket.

Touchpoints were designed with safety and security in mind. We ensure this a few different ways:

  1. Data Access Control: MindTouch site administrators have control over which domains or subdomains can embed their Touchpoints, and read data from their MindTouch site.
  2. JavaScript Isolation: The bootstrapping code uses an unique namespace which provides isolation from any JavaScript loaded on the page.
  3. Content Isolation: Once the JavaScript bootstrapping code is executed, a sandboxed frame is created and populated with the Touchpoint user interface.

Data Access Control with CORS

Touchpoints are built on top of web technologies like HTML and JavaScript, so naturally a web browser is required to load and display them. However, Touchpoints load data from a MindTouch site and display it another web application or website. This may not sound so bad, until you understand a major caveat of cross website HTTP requests.

The best way I have found to describe the pitfalls of cross website HTTP requests, is a bank website analogy. You first sign in to your bank’s website. In order to identify you as signed in, a cookie is saved on your computer. You then open another tab in your web browser and type in the following:

What if evil.example.com executes JavaScript that invokes an HTTP request to your bank website? It would send your cookie, your bank would identify the request as having come from your identity, and respond with potentially sensitive, private data. Finally, evil.example.com could reroute that data to a storage mechanism and peruse through your data with their grubby, evil fingers.

Same-Origin Policy, as implemented by modern web browsers, blocks all JavaScript code from reading response data from cross website HTTP request invocations. This ensures that a web browser’s authenticated session on one website, can’t be hijacked when navigating to another website. Cross Origin Resource Sharing (CORS) provides the tools to circumvent Same-Origin Policy in a controlled manner. Web applications can provide HTTP response headers to ease restrictions, allowing for a flexible, yet secure approach. Same-Origin Policy and CORS are fundamental to ensuring that Touchpoints do not become liabilities for MindTouch site users.

Let’s take a look at the HTTP request and response flow to see how MindTouch uses CORS to mitigate cross website security issues, and how Touchpoints can load without disturbing the layout of the webpages they are hosted on.

The Touchpoint Embed Code

The web browser loads a web page and discovers a Touchpoint embed code inside the HTML. A Touchpoint embed code consists of two script HTML elements. The embed code is generated when a MindTouch site administrator creates and configures a Touchpoint in their MindTouch administration dashboard. The first script element downloads the Touchpoint bootstrapping code, the second is a place holder that will be injected with the Touchpoint user interface itself, should the Touchpoint successfully load.

The ID (starting with “7b78537…”) in both the elements represents a unique Touchpoint entity. If two Touchpoints are embedded on the same webpage, even if they were generated from two different MindTouch sites, they will never have the same ID. The ID is non-deterministic, but unique to the entire MindTouch cloud infrastructure.

Bootstrapping a Touchpoint

If the request URL references an existing Touchpoint, the MindTouch API responds with the Touchpoint bootstrapping code. The Touchpoint bootstrapping code provides two things: a URL to download the Touchpoint execution code bundle and the configuration properties of the Touchpoint entity. On MindTouch sites that are localized in languages other than English, the bootstrapping code returns the localized text that the Touchpoint should display.

There is an execution code bundle for each type of Touchpoint (a search bar, a contextual help popup, or a sign in widget, etc.). Each bundle is a specialized implementation of our internal Touchpoint SDK, which in turn is built on top of MindTouch’s common JavaScript API, Martian. Martian is designed to be modular and is written with modern ECMAScript features such as Promises. Due to the lack of native module support in modern browsers, and the lack of ES2015 syntax in others (I’m looking at you IE11), we use JSPM (and by extension Babel and System.JS) to bundle and ship Touchpoints today. However, we all recognize that JSPM is simply a means to end, and our eye should be on shipping modules or even Web Components (which I will address on later in this post).

The execution code bundle creates (or if another Touchpoint on the webpage has already loaded, simply references) the MindTouchWebWidgetFactory object in the hosting webpage’s DOM. The factory creates a new Touchpoint DOM object and loads it with the unique properties of that Touchpoint. The creation of this object in the DOM and its subsequent method execution is the only JavaScript we will be executing on the webpage where the Touchpoint is embedded.

The two key properties to take note of are token and embedId. These will be used in the following steps to verify that the Touchpoint is allowed to load and where it will display.

Loading a Touchpoint

The token, from the bootstrapping code, will be used in a cross website fetch request to verify that the webpage’s domain origin is in the list of domains that are allowed to embed the Touchpoint. In order to send this value, as a X-Deki-Token header, the web browser first sends an OPTIONS request to the MindTouch API. The OPTIONS request is sent because X-Deki-Token and X-Deki-Web-Widget-Embed-Location are not IETF standard HTTP headers, and the web browser, via CORS, gives the MindTouch API the decision of whether or not the request should even be sent.

The MindTouch API responds with a series of Access-Control-Allow-* headers, detailing the HTTP headers and methods that may be sent, along with which domain origin is allowed to send them. The web browser has not actually sent the X-Deki-Token header yet, so we must allow the domain origin access to send the header.

Now the web browser sends the first request, an impression event. MindTouch uses this to register that a Touchpoint has loaded for analytics purposes. It also serves as a mechanism to possibly stop the Touchpoint from loading. Touchpoint loading is stopped if the Origin header’s value does not match a domain origin that is in the domain origin lookup table, using X-Deki-Token as the key. The owner of a third party website cannot influence or change the values of this lookup table, it is only populated when a MindTouch site administrator whitelists which domains or subdomains can embed their Touchpoints.

I find it interesting when someone asks me

Can’t someone just copy that X-Deki-Token value and send it to the MindTouch API whenever they want?

Of course they can, but what would be the point? Receiving Access-Control-Allow CORS headers outside of a web browser’s CORS flow is pretty much useless, aside from testing. What only matters is how the MindTouch API responds when the web browser sends the token, and CORS is implemented in modern web browsers to be safe from tampering.

Sandboxing a Touchpoint

The impression event request was successful, and we can now display the Touchpoint. The embed id, from the Touchpoint bootstrapping code, is used to find the script HTML element, with the matching id property. The script HTML element will be injected with the Touchpoint user interface. The current sandboxing approach involves creating an iframe element, without a src attribute, and populating the DOM inside it. From this point on, any Touchpoint functionality is limited to everything inside the iframe. There is one notable exception, the Contextual Help Touchpoint.

Displaying Contextual Help

The Contextual Help Touchpoint is a mini web browser that provides navigation of a MindTouch site’s authoritative content. It’s deployed along side a button that reads something like Help or Learn More. Clicking this button covers the webpage’s content with a darkened overlay, and the mini web browser floats on top of it. Obviously to achieve this, we were required to manipulate the DOM outside of an iframe, as little as possible.

Many MindTouch content pages displayed inside a Contextual Help Touchpoint are longer than the height of the iframe. Therefore, the Touchpoint requires scrolling. We found it was very easy for the scroll events intended for the iframe content to be picked up by the outer DOM. Therefore, when the Touchpoint opens it sets the styles height: 100% and overflow: hidden on the outer DOM body element.

As mentioned before, when the Contextual Help Touchpoint opens, a darkened overlay covers the outer DOM content. In order to cover everything on the page, we must know the z-index of the highest element on top of the DOM stack. On a single page application this can change frequently, so it must be calculated every time the Touchpoint is opened. The basic approach is to iterate through all the elements on the outer DOM, and find the z-index property of each one, after getting their computed styles. A z-index is a 32-bit signed integer, so the highest possible value is 2147483647. Obviously when iterating over possibly large collections, and working with max integer values, a considerable amount of safety needs to be included in the solution.

Vorsprung durch Web Components

This is a very exciting time to be developing web applications. Advancements in web browser capabilities are moving at a fantastic pace and Touchpoints were designed with an eye to the future. Web Components are a new web browser standard that is currently under development. This standard enables the creation of reusable user interface widgets, like Touchpoints, using open Web technologies.

MindTouch is not very keen on adding third party JavaScript frameworks, as we generally do not want to lock into the development path of non-web standard libraries. However, we are willing to explore Google’s Polymer project as a replacement for some our Touchpoint implementations, as the result is Web Components (or at least the polyfills that will enable them). Shadow DOM is a natural replacement for our iframe sandboxing approach, and Custom Elements can replace the placeholder script element in the Touchpoint embed code.

MindTouch Engineering

We build and operate the best self service support experience in the world. https://mindtouch.com/about/careers

James Andrew Vaughn

Written by

I'm a @MindTouch product manager, a black belt instructor, and a modern furniture and spaces aficionado. My friends call me Andy.

MindTouch Engineering

We build and operate the best self service support experience in the world. https://mindtouch.com/about/careers

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade