Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a Meteor app in an iframe from a different domain

Tags:

iframe

meteor

After weeks of work I was now finally ready to deploy my app just to find out that meteor doesn't seem to run in an iframe. It works fine when the top level window and the iframe run on the same domain, but not when the domains differ. The error I'm getting on Chrome is:

Uncaught SecurityError: Access to 'sessionStorage' is denied for this document. 

After that error, the initialization of Meteor seems to stop and not even Meteor itself will be defined.

After some digging, I found this reference and explanation: http://www.w3.org/TR/webstorage/#user-tracking : "Blocking third-party storage User agents may restrict access to the localStorage objects to scripts originating at the domain of the top-level document of the browsing context, for instance denying access to the API for pages from other domains running in iframes."

The problem is not specific to my app. You can take any of the demo apps in the meteor gallery and try to embed them in another page with an iframe and you'll see what I mean.

Is there any way around this?

Edit 2014-01-07: I have tried wrapping some of the places where exceptions are thrown in try-catch blocks, but got the impression that that was crippling meteor too much, such that it wouldn't properly initialize for a different reason.

like image 686
Christian Fritz Avatar asked Jan 04 '14 17:01

Christian Fritz


2 Answers

I'm unable to reproduce the specific issue you're having, but here are the steps I followed in order to get it working. Perhaps we can deconstruct it from there and figure out what the error is.

I created a blank application:

meteor create testapp

then I added the browser-policy module:

meteor add browser-policy

Then I edited testapp.js to make it use the Session:

if (Meteor.isClient) {
  Template.hello.greeting = function () {
    return Session.get( 'welcome_text' );
  };

  Template.hello.events({
    'click input' : function () {
      // template data, if any, is available in 'this'
      if (typeof console !== 'undefined')
        console.log("You pressed the button");
        Session.set( 'welcome_text', 'Hello: ' + Math.random() );
    }
  });
}

if (Meteor.isServer) {

  BrowserPolicy.framing.allowAll();

  Meteor.startup(function () {
    // code to run on server at startup
  });
}

I created two nginx virtual hosts:

server {

    listen 80;
    server_name test1.com;

    location / {
        proxy_pass http://127.0.0.1:3000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

}


server {

    listen 80;
    server_name test2.com;

    location / {
        alias /websites/test2.com
    }

}

test1 is the meteor app and test2 is the iframe.

For test2, I created /websites/test2/index.html:

<iframe src="http://test1.com">

Then I added test1.com and test2.com to my hosts file and started the meteor app.

I went into http://test2.com on the browser, and everything works as expected. It looks like you've tried these steps more or less, but your application or server stack may have other components that are interfering with browser-policy.

I'd start by updating your question to include the request and response headers for the meteor app. Also, is your meteor app running behind a proxy?

like image 158
0x6A75616E Avatar answered Oct 21 '22 15:10

0x6A75616E


As far as I know, the short answer to your question is no. I don't think there's a way to manipulate session variables through an iFrame. I think it's a security thing. If you give the reason why you need an iFrame and/or its context, I could try to come up with a solution that works around it, but I don't think it can be done with iFrames alone.

EDIT: Based on what you've said, it sounds like you need an API. The package I'd suggest for this is called RestStop2, which allows you to build easy RESTful APIs with Meteor. Check it out.

like image 38
mjkaufer Avatar answered Oct 21 '22 14:10

mjkaufer