Render WebDirect in an Iframe

  • 11

Render WebDirect in an Iframe

Tags : 

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?

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.

Before we get started it may be helpful to see an example of a framed WebDirect app in production. If you’ve visited our Downloads page recently, you already have. That page uses a framed WebDirect app to collect contact details before providing access to file downloads. The parent elements (header, navigation bar, footer, etc.) are the exact same as other sections of our website. Changes we make to the WebDirect app via FileMaker Pro get pushed to the framed element, and changes we make to our website’s template get pushed to the parent elements.

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.


11 Comments

Jason

March 17, 2018at 8:59 am

This is pretty cool. I’m assuming it still uses a WebDirect connection license?

    Shawn

    March 19, 2018at 8:08 am

    Yes, it takes a user connection license via WebDirect.

Vini

June 1, 2018at 6:35 am

Thanks for all this info. I see that Filemaker Server 17 seems different… do you know which file(s) in FM Server 17 would have to be modified in the same way?

    Ian Harris

    June 1, 2018at 1:12 pm

    I tested on one of our 17 servers and confirmed the configuration change is the same as 16.

    On your 17 server, look for the web.config file located within “C:\Program Files\FileMaker\FileMaker Server\HTTPServer\conf”. Then make the changes outline in the blog post.

      Vini

      June 1, 2018at 1:24 pm

      Hi Ian, thanks very much for your reply… but there’s no web.config in that specific folder anymore…! that’s why I was wondering if they’ve put the file somewhere else, or the change has to be made on a file named differently? thanks again!

        Ian Harris

        June 1, 2018at 2:24 pm

        I checked a fresh installation of 17 and found the web.config file in the same location as 16. You could create your own web.config file manually, but I would recommend reinstalling 17.

        It’s also possible the file is hidden. See here about showing hidden files using PowerShell: https://blogs.technet.microsoft.com/heyscriptingguy/2015/12/27/powertip-display-hidden-files-in-powershell/

          Vini

          June 4, 2018at 8:39 am

          Hi Ian, thanks again for your explanation. I just realized that the whole time your comments were based on windows! And I was just trying this on a Mac!

          This being said, in FM server 16 both files structures from Windows/Mac were pretty much identical… at least regarding the location of that “conf” folder (once you’re in the FileMaker server folder) and actually it’s content as well looked like was equal. It seems that in FMS 17 they left the windows version pretty much identical in terms of files structures/locations as it was in FMS 16 but in the Mac version they moved things around a bit…

          Just so you know (and others that may read this) the “conf” folder is still located at the same place but now there’s 2 files that replaces the previous “web.config” and they are “htppd.conf” and “httpd.conf.2.4”. I’m still not sure why there’s 2 and which one should be changed, but I guess I’ll do it on both just to be sure. The content of the files have been altered as well, in terms of the locations of the “X-frame-Options” information and “X-XSS-Protection”, they are now separated by a few other options… So, I guess that’s it.. I have to try it now! thanks again

          Ian Harris

          June 4, 2018at 11:20 am

          Hi Vini,

          Thanks for the update! That’s definitely an important distinction. I’ve edited my post to direct MacOS users to your comment.

          FileMaker Server on MacOS uses Apache, which is why the config files are named “httpd.conf” and “httpd.conf.2.4”. Windows uses IIS, so the config files are named “web.config”. The syntax will differ between IIS and Apache config files but they share many of the same default directives.

Vini

June 14, 2018at 9:17 am

Hi Ian, thanks for everything.. I have another quick question… what if I’d like the solution to be embedded in 2 different websites, with different domain… (and of course only these 2) do you know if that would be possible? I also see that you have a “load demo” button.. which I think is good because it doesn’t load the solution right away.. how did you do that? thanks again

    Ian Harris

    June 14, 2018at 10:03 am

    Hi Vini,

    The content-security-policy (CSP) directive allows for whitelisting of multiple domains. The x-frame-options allow-from directive only allows whitelisting of one domain at a time. CSP “obsoletes” x-frame-options, meaning if a browser supports CSP it should use CSP and ignore x-frame-options (see here: https://www.w3.org/TR/CSP2/#frame-ancestors-and-frame-options). So your scenario is possible as long as clients are using browsers that support CSP. Here’s a helpful blog post about whitelisting multiple domains using CSP (note their examples are for an Apache config file not IIS; their examples can be reworked for IIS): https://oxdef.info/csp-frame-ancestors/

    The “load demo” button works using a bit of JavaScript. When you click the button it populates the iframe tag’s “src” attribute, then hides itself.

    The button:

    <button id="init-demo" onClick='document.getElementById("webd-iframe-blog").src="https://web.app.works/fmi/webd/Demo-Iframe-WebDirect?homeurl=https://web.app.works/fmi/webd/Demo-Iframe-WebDirect";document.getElementById("init-demo").style.visibility = "hidden" '>Load Demo</button>
    

    The iframe:

    <iframe id="webd-iframe-blog" style="height: 500px; width: 100%; overflow: hidden; border: 0;" scrolling="no" seamless="seamless"></iframe>
    

      Vini

      June 14, 2018at 7:58 pm

      This is all great Ian! thank you very much!

Leave a Reply

fourteen − six =