See related issue expressed in ELMSLN: https://github.com/elmsln/elmsln/issues/333

If an H5P item is created on a domain other then the one that it's going to be displayed in (via iframe) it can have issues of cross-domain policy.

To avoid this, a document.domain value needs to be added to the scripts loaded into embed.php which then allows it to operate correctly.

Is there a way to better support this? We're going to provide a patch in our project that allows for using the domain property correctly from the installer but was wondering if there was a way to get a configurable variable that might make this easier.

Comments

btopro created an issue. See original summary.

icc’s picture

Could you provide a little more detail about how you are using H5P, and why access to the iframe is required? This could give us some more insight and make it easier to pick a solution that will benefit others as well.

It sounds like you're hosting your H5P content on one site and including it into the LMS using the embed code.
One of the obvious risks of setting document.domain is compromising the security. An alternative solution might be to set the same-origin policy in the web server's config, but I guess it's not very convenient if this ELMSLN is more of a product than a service.

Why is it you require access to the iframe, is it for altering the content or are you just gathering information, e.g. xAPI events? If it is the latter I believe it might be safer and more flexible if H5P post messages to the parent window through the H5P.communicator instance. This is the same way H5P triggers the parent window to resize the iframe.

btopro’s picture

We currently also support the iframe resizing thing via drill down / passthrough to dynamically resize self. I believe the usecase is xAPI events though if you were operating on known sub-domains (like an asset management system talking to the place you embed stuff on the same base.domain) then I think it makes sense to have it as an option. If in Drupal land it's a possible variable to set that is added to the drop of embed.php if the user choses to use it.

Definitely integration / edge-case but increases flexibility of the systems used to manage H5P instances

btopro’s picture

Version: 7.x-1.11 » 7.x-1.x-dev
Status: Active » Needs review
StatusFileSize
new384 bytes

patch to provide a more generalized solution; a drupal_alter that fires before embed.php is spit to the screen. This allows for things to (easily) implement appending whatever output they want.

heyMP’s picture

StatusFileSize
new384 bytes

I updated the patch to fit the latest version.

icc’s picture

A hook would be nice, but in its suggested state it might seem a little redundant to have a hook that brings nothing but context. I mean, it doesn't provide any of the data "calculated" in the function, simply the node object, so in theory, it would be very much the same as a node alter hook checking if current_path() equals 'h5p/embed'.
However, a more specific hook for altering the h5p content "object" could be handy in many cases, and with a display variable to determine if it's embedded or not.

kenianbei’s picture

Just wanted to add my two cents here... It seems to me that the main problem is since version 7.50, Drupal has added SAMEORIGIN to X-Frame-Options in order to prevent clickjacking. This prevents all iframe embeds from any other domain.

I've been getting around this through a menu alter:

function MODULE_menu_get_item_alter(&$router_item, $path, $original_map) {
  if (isset($router_item['path']) && $router_item['path'] === 'h5p/embed') {
    drupal_add_http_header('X-Frame-Options', FALSE);
  }
}

I'm wondering if it would be better to make this an option in the H5P settings for sites that wish to allow cross-domain embeds?

icc’s picture

@kenianbei Thanks, I've created a separate issue for implementing your suggestion: https://h5ptechnology.atlassian.net/browse/HFP-1467

kenianbei’s picture

Also just wanted to post a D8 solution as well since I'm starting to use this in D8 and having the same issue. For D8 you can disable the header site wide as per this stack overflow issue. You can also add a per path by altering the code posted in the stack exchange issue:

class RemoveXFrameOptionsSubscriber implements EventSubscriberInterface {

  public function RemoveXFrameOptions(FilterResponseEvent $event) {
    $response = $event->getResponse();

    if (preg_match('/^\/h5p\/[0-9]+\/embed$/', $event->getRequest()->getPathInfo())) {
      $response->headers->remove('X-Frame-Options');
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('RemoveXFrameOptions', -10);
    return $events;
  }
}
icc’s picture

Ah great, thanks for sharing!