[SOLVED] Methods not working when is in Iframe

Hello,

Working on a pet project I’d like to allow other website to setup my meteor/react application in an Iframe.

They do a simple Iframe and reference my URL: the site shows but the methods don’t seem to be working. No error in console. When I check the network tab

I just tried without and now with:

import { BrowserPolicy } from “meteor/browser-policy-common”;

and this line on server side:

BrowserPolicy.framing.allowAll();

Without it the site loads normally but when I try to trigger a method nothing happens. It’s supposed to fetch data on the server and display them and nothing changes.

if I add the BrowserPolicy I loose my fonts, get the following error:

Error with Permissions-Policy header: Unrecognized feature: ‘interest-cohort’.

My only goal is to have my app embaddable and usable as if it was on the main domain in any other website. Just like a widget. Anyone succeeded with this ?

Use webApp and create a route if you want to do this then set the CORS headers in there with webapp

1 Like

Thanks for the lead, though not sure what you mean by this. Would you have an example of working solution for iframe ? What’s weird for me is that the app loads and I can interact but can’t call server method.

Sounds like browser sandbox preventions to stop a async request from inside a iframe. See if you can run a async call and if it gets blocked that is why.

Why do you run it inside a iframe and not just inject into the page with a script tag?

Below example for https://your-app.com/my-route

WebApp.connectHandlers.use('/my-route', (req, res, next) => {

  //Open CORS
  res.writeHead(200,{'Access-Control-Allow-Origin': '*'});

  var url = req.originalUrl; //will output the URL of the page requesting


  res.end(url); //send an output
});

The idea of the iframe was to make it easy to be used as a widget on WP sites for example. They just do the iframe with the website and it’s ready to work, but seems it’s block like this.

Gonna try your solution as such for the iframe in order to get the whole website and keep you posted. Thanks for the much appreciated help.

WebApp.connectHandlers.use('*', (req, res, next) => {

  //Open CORS
  res.writeHead(200,{'Access-Control-Allow-Origin': '*'});

  var url = req.originalUrl; //will output the URL of the page requesting


  res.end(url); //send an output
});

Ok in this instance you can very simply have a piece of javascript in-front of the request so you can include <script src='my-app.com/script.js'> and that is in your /public then inside of that you can do all of your frontend markup GUI stuff in javascript, and async call the route you made with webApp, then it’s just a case of formatting the output and adding it to the DOM. So wp sites just have to add a script tag and be done with it.

This gives you alot of flexibility and you can even include a token into the request and add that into your meteor account system so the plugin is mapped to user accounts and paid subscriptions etc

Yep seems that will be the approach to use cause I just added your code to the app and the iframe is still not working. I thought this solution would be much easier, still two minded why meteor app can not be iframed.

Some silly questions:

  • You use the route to webapp to call your api right ? so I have my-app/api route where is send post or get request from the /public/myscript.js and send back the data to be displayed.
  • the js in the public folder needs to be plain js right, can not have react in there ? would be much easier to do it in react for me, but I feel if I just install react in the app it’s not gonna work in the public folder, am I wrong ?
  • You mention token for the widget in WP, where would you store them securely ?

thanks a bunch

Adding my code example wont fix your iframe, the example is for creating a webapp route.

iframes are restricted somewhat by the browser’s sandbox, so cannot make remote calls over the network to prevent exploits and cross site forgery. Although across the same domain it can permit it - more info Iframes and communicating between applications - DEV Community

In answer to your questions:

  1. The post or get is sent to the webapp route, and then it will be inside the req variable.
  2. Yes although you can include react components and render it SSR if required, the script is just a middleware to get you into the page’s DOM you can then add the elements just as regular with jquery or vanilla js.
  3. The token is something you can create and store in the users collection, you can use a secure tokens library or just create a hash for an api key. This just means they can request like <script src='my-app.com/script.js?APIKEY=HASH-GOES-HERE'> and that is obfuscated so no username is exposed. If they stop paying their subscription you simply turn that apikey off so when the route runs it checks if the key is live, if it returns false from db it just doesn’t do anything else. If you are thinking of doing a full JSON API then it would be worth using Json web tokens to secure it properly and sign each message with a token (jsonwebtoken - npm) but for a small thing it’s probably overkill.
1 Like

This code you posted wont work man, best to read the manual and learn how to use webApp.

1 Like

Meteor apps in iframes usually just work, i just tested this in Tryit Editor v3.7

The iframe cannot communicate with the page that embeds it, its completly isolated (if its not on the same domain), but otherwise it can do what every webpage can do, including doing websockets or http requests.

Any webpage can prevent beeing embedded into an iframe though through headers (which will be honored by normal browsers). The parent page that declares the <iframe> can also prevent the iframe from doing certain things, see <iframe>: The Inline Frame element - HTML: HyperText Markup Language | MDN

so check if the ones that integrate your webpage as an iframe have delcared certain sandbox properties.

2 Likes

Thanks I’ll have a look! I was also surprised it didn’t work, especielly as first load work, just calls to server. I’ll check the headers on the ‘host’ site calling the iframe see if anything could be blocked.

@macrozone on the meteor, the one I want to be embedded in other website, what do you recommend to make sure it’s embeddable, helmet and ‘Access-Control-Allow-Origin’: ‘*’, or rather using browser policy or shall normally the default settings be embeddable ?

He wants to use method which uses a rpc call cross-domain.

nothing in particular, i think you can leave it as default.

can you check whether your app works when embedded in this iframe example: Tryit Editor v3.7 ?

if yes → these other websites declared sandbox properties on the iframe to block certain request types within your iframe

if no → something is wrong on your app

maybe you can share your app url?

no, not how @ivo described it.

consider domain-a.com and i-am-embeddable.com

now domain-a.com has an <iframe src="https://i-am-embeddable.com" />, then the embeeded iframe can do requests to i-am-embeddable.com, this is not cross-domain, the iframe will act as it were a completly independent browser window on its own.

Of course, the iframe cannot do requests to domain-a.com, but that is not required here.

But maybe some information is missing from @ivo’s side?

@macrozone This was the original that we are discussing. It’s the methods call that wont work because of sandbox. If its cross domain even with Cors headers it wont run in iframe so must use script tag and an async Xmlhttp request. Even then some antivirus and adblock software can block it.

Yes it works on tryit editor, so I guess it’s what you mentioned with the sandbox properties. Any idea where I could find clear documentatoin to inform the site owner what they have to do in order to make it work on their side.

You’re perfectly right with your example, I just want i-am-embeddable.com to work on its own, no need to have any communication with domain-a.com

So it works on tryItEditor but doesn’t on a test site from a customer. I’m just still a bit in the blur of what recommendation to give to the site owner. Thanks so much for the help and time.

check this docu: <iframe>: The Inline Frame element - HTML: HyperText Markup Language | MDN

check whether they have additional properties declared on the iframe.

Having said that, there is no sand-box property that would prevent the iframe from doing requests (“ajax” / fetch / websockets). Also if you look at these SO-threads they confirm that its not possible to block http requests in an iframe: html - How to make the iframe block requests from certain domains? - Stack Overflow, javascript - HTML5 Iframe: Block remote requests - Stack Overflow

So i am actually curious how they managed to block your iframe from doing requests. So maybe share some code or even link to the page where your iframe is embedded…?

what you can do however is disabling javascript completly, but i doubt that this is the case (unless you do SSR with meteor).

what you can do however is disabling javascript inside

1 Like

Thanks, everything is unfinished work so all the sites are work in progress but here is the link to reproduce:

The immobourse site ain’t mine to deal with, we just wanna test the iframe on it right now. The idea is that people who will want to add the iframe won’t probably be too tech friendly so the simplest way to make it work would be great :smiley:

You see the iframe, you can choose an address but when you click on the launch search button nothing happens while it should search on the meteor app https://app-71218a48-283c-447f-a5d2-72a85bffdcf2.cleverapps.io/ which work in tryIt Editor with the iframe.

if i open the iframe url directly, i can’t do anything either.

(can’t link the screencast though)

Maybe i don’t use it correctly though…

So i doubt it has anything to do with it beeing embedded in a iframe at all. Looks like you have some local or session data. Try a fresh browser or browser session (Guest window or so) and check if it works there

Additionally, the page is not served through https which i would avoid. In particular you should not embedd http content inside a https page (and vis-versa)