Laravel 4.1.x – Blank iframe – default X-Frame-Option header set to SAMEORIGIN – Fix (Facebook Page App Tab)

Have you ever experienced a blank page/frame when embedding a Laravel app in an iframe (e.g. Facebook Application in a Page Tab)?

I ran into this subtle issue when I was making a Facebook Page Tab Application that embeds an app (using Laravel 4.1.x as the framework) in an iframe. I was able to troubleshoot this issue further by using Firebug/Google Dev tools to point me in the right direction. In:

  • Chrome Dev Tools: I was getting an error of “Refused to display ‘https://xxxx.xxx’ in a frame because it set ‘X-Frame-Options’ to ‘SAMEORIGIN'”
    chrome_xframe
  • Firebug: I was getting an error of “Load denied by X-Frame-Options: https://xxxx.xxx does not permit cross-origin framing.”
    firefox_xframe

It turns out in Laravel 4.1.x, by default there is something called the “FrameGuard” that sets the X-Frame-Option in the HTTP headers to SAMEORIGIN, which means page can only be displayed in a iframe from the same origin (the domain itself). This is a security feature added that was intended to preventclickjacking.”

There is a discussion thread outlining the addition and proposed implementation on github (see references). In 4.1.x it was deemed fine to be activated “out-of-box”; however, in retrospect many issues have been raised by users and it will be disabled by default in Laravel version 4.2.

For users who are still using Laravel 4.1.x and want to disable the FrameGuard, all you need to do is edit the start.php file in the “bootstrap” folder and add the following line before the return statement.

  • App::forgetMiddleware(‘Illuminate\Http\FrameGuard’);

So for example in my start.php, I have (notice before the “return $app;”):

  1. require $framework.'/Illuminate/Foundation/start.php';
  2.  
  3. /*
  4. |--------------------------------------------------------------------------
  5. | Return The Application
  6. |--------------------------------------------------------------------------
  7. |
  8. | This script returns the application instance. The instance is given to
  9. | the calling script so we can separate the building of the instances
  10. | from the actual running of the application and sending responses.
  11. |
  12. */
  13.  
  14. App::forgetMiddleware('Illuminate\Http\FrameGuard');
  15.  
  16. return $app;

This will remove the FrameGuard and allow users to use Laravel in an iframe (that is of different origin). Or in my case, allow my Facebook app to be embedded within an iframe in my Facebook Page Tab.

I can see how this issue could be frustrating to many developers as the error is not particularly overt, nor is this type of Framework change particularly clear or obvious in any way.

Reference: https://github.com/laravel/framework/issues/1725 and https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options

12 thoughts on “Laravel 4.1.x – Blank iframe – default X-Frame-Option header set to SAMEORIGIN – Fix (Facebook Page App Tab)

  1. Just in case this helps someone else, I had to do:

    $app->forgetMiddleware('IlluminateHttpFrameGuard');

    or it broke everything – because I had already instantiated the $app to setup detectEnvironment calls etc.

  2. Hi, Please help me to solve the issue. I was getting the above mentioned problem in Laravel with Facebook App. After that I have added the following line in start.php

    App::forgetMiddleware(‘IlluminateHttpFrameGuard’);

    After that the blank page issue gone and I have received Illuminate Session TokenMismatchException error. Please advice.

    • Laravel 5 is not affected by this Middleware issue. By default FrameGuard does not seem to be turned on.

      I did a quick test and also looked in the HTTP headers that a default Laravel 5 project generates and it seems to confirm this.

      • I still get this error when I try to load a youtube movie in a fancybox iframe

        • Your above issue does not feel like it is Laravel-related. It sounds like a cross domain issue to do with ajax/client-side JS code where you’re trying to pull in a video from a 3rd party (youtube) server.

          • Thanks! You were right, it was youtube that caused the issue.

Leave a Reply

Your email address will not be published.