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:
- Data Access Control: MindTouch site administrators have control over which domains or subdomains can embed their Touchpoints, and read data from their MindTouch site.
Data Access Control with CORS
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:
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.
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.