Render WebDirect in an Iframe

render webdirect in an Iframe

Let’s talk about Iframes. Is there a feature you want to add to your website that you could quickly implement using FileMaker but not using the language your site’s programmed in? You could send users to a WebDirect app, but replicating all of your website’s design elements in FileMaker can be time consuming. Plus, if your site’s style is not carefully carried over to WebDirect, you risk weakening your brand’s cohesiveness in the eyes of users. What if you could create the feature in FileMaker and drop it into a page of your website as a component, letting your website’s theme take care of unrelated components like headers, navigation bars, and footers?

HTML Iframe

The HTML Iframe element loads another website or web resource as a child element of the surrounding page. They’re useful in cases when there’s an external resource you’d like to serve to visitors of your website, but you do not want to send visitors to a whole new site. Most if not all modern browsers support Iframes, and you can even include multiple Iframe elements on a single page. This post describes how to embed a FileMaker WebDirect solution within a website using an Iframe element.

To accomplish this we had to make a few server-side configuration changes. By default, FileMaker Server’s HTTP response headers only allow pages to load WebDirect content within an Iframe if those pages have the same origin. According to Mozilla, “pages have the same origin if the protocol, port (if one is specified), and host are the same for both pages.” For example https://app.works/downloads/ and https://app.works/project-give2017/ have the same origin, but https://app.works/blog and https://differenthost.app.works do not. This is the default configuration because it prevents other sites from surreptitiously framing your FileMaker WebDirect solution. Without the right response headers in place, your app would be vulnerable to attacks like Cross-Frame Scripting.

Luckily, you can maintain your site’s security and take advantage of Iframes by using Content-Security-Policy (CSP) and X-Frame-Options response headers. These headers tell web browsers whether or not to load a page within an Iframe. CSP, the newer and more robust of the two headers, lets you specify which sources to trust for specific resource types using what are called directives. For example, you can use the “font-src” directive to define https://fonts.google.com/ as the only valid source of fonts for your page. In the case of framing WebDirect, the CSP directive we care about is “frame-ancestors”, which lets us define who can frame our app.

X-Frame-Options has been deprecated in favor of CSP, however it still needs to be included in order to support certain browsers including Internet Explorer. If your web server’s response headers include CSP but not X-Frame-Options, browsers that do not support CSP will assume you have not set any restrictions on who can frame your site. Unfortunately, X-Frame-Options only provides three options: do not allow framing at all, allow same origin framing, or allow from one specific origin (single frame ancestor).

Now that the details are out the way, here’s how you implement these response headers. In the following steps I’ll assume you’re running FileMaker Server on Windows. If you’re wondering where to make these configuration changes on MacOS, please see the comment below from Vini.

  1. Open File Explorer and go to this folder: C:\Program Files\FileMaker\FileMaker Server\HTTPServer\conf 
  2. Copy a backup of the file C:\Program Files\FileMaker\FileMaker Server\HTTPServer\conf\web.config to another folder like the Desktop. If you make an irreversible edit to the web.config file, you can simply restore your backup copy.
  3. Run your preferred text editor as administrator and open the web.config file.
  4. Scroll to the bottom of the file. Add or edit the <customHeaders> element to include the Content-Security-Policy and and X-Frame-Options headers.
  5. Save and exit the web.config file.

One last change is needed to ensure your WebDirect app renders within an Iframe. In Safari 11, Apple enables the “Prevent cross-site tracking” privacy preference by default. This preference prevents cookies from being set across domains if the user has not already visited the domain setting the cookie. In other words, if https://your-parent-site.com frames https://your-webdirect-app.com and a user at https://your-parent-site.com has never visited https://your-webdirect-app.com, Safari will not allow https://your-webdirect-app.com to set cookies as a frame element.

To workaround this setting, a few lines of JavaScript code (courtesy of Github user vitr) at both the parent site and the framed site are necessary. First, add this code to the parent site’s html within a script tag:

// Safari 11.0 cross-site tracking support.
// If the user is browsing in a Safari Private Window,
// browse to the framed site. The framed site should then
// set a cookie and navigate back to the original site.
// Reference: https://github.com/vitr/safari-cookie-in-iframe
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
if ((is_chrome) && (is_safari)) {is_safari = false;}
if (is_safari) {
if (!document.cookie.match(/^(.*;)?\s*fixed\s*=\s*[^;]+(.*)?$/)) {
// JavaScript at https://your-webdirect-app.com/cookie.html sets a cookie and
// navigates back to https://your-parent-site.com.
window.location.replace("https://your-webdirect-app.com/cookie.html");
}
}

Second, create a file called “cookie.html” and save it within the C:\Program Files\FileMaker\FileMaker Server\HTTPServer directory. Then add these lines to cookie.html within a script tag:

// Reference: https://github.com/vitr/safari-cookie-in-iframe
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
// Chrome has Safari in the user agent so we need to filter (https://stackoverflow.com/a/7768006/1502448)
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
if ((is_chrome) && (is_safari)) {is_safari = false;}
if (is_safari) {
// See if cookie exists (https://stackoverflow.com/a/25617724/1502448)
if (!document.cookie.match(/^(.*;)?\s*fixed\s*=\s*[^;]+(.*)?$/)) {
// Set cookie to maximum (https://stackoverflow.com/a/33106316/1502448)
document.cookie = 'fixed=fixed; expires=Tue, 19 Jan 2038 03:14:07 UTC; path=/';
window.location.replace("https://your-parent-site.com");
}
}

With these changes applied, your framed WebDirect app should render correctly in all modern browsers while still being secured against unwanted framing.


*This article was originally written for AppWorks, which has since joined Direct Impact Solutions. This article is intended for informative purposes only. To the best of our knowledge, this information is accurate as of the date of publication.