Embedding a live view as an Iframe

I have two phoenix applications. One is dummy running at port 4001 and the other is dummy2 running at port 4000. I want to embed a live view from dummy2 as an iframe in dummy.

In order to achieve my goal, I removed :put_secure_browser_headers plug from router.ex. I also have this following code in my app.js for live view to work as it couldn’t access window.localStorage and window.sessionStorage from the iframe.

class InMemoryStorage
   {
      constructor() { this.storage = {} }
      getItem(keyName) { return this.storage[keyName] }
      removeItem(keyName) { delete this.storage[keyName] }
      setItem(keyName, keyValue) { this.storage[keyName] = keyValue }
    }

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
  params: {_csrf_token: csrfToken},
  localStorage: new InMemoryStorage,
  sessionStorage: new InMemoryStorage
})

When I try to embed the live view from dummy2 in dummy, the live view is getting constantly getting reloaded every second. In the server of dummy2, I’m seeing this following message appear constantly.

[debug] LiveView session was misconfigured or the user token is outdated.

1) Ensure your session configuration in your endpoint is in a module attribute:

    @session_options [
      ...
    ]

2) Change the `plug Plug.Session` to use said attribute:

    plug Plug.Session, @session_options

3) Also pass the `@session_options` to your LiveView socket:

    socket "/live", Phoenix.LiveView.Socket,
      websocket: [connect_info: [session: @session_options]]

4) Ensure the `protect_from_forgery` plug is in your router pipeline:

    plug :protect_from_forgery

5) Define the CSRF meta tag inside the `<head>` tag in your layout:

    <%= csrf_meta_tag() %>

6) Pass it forward in your app.js:

    let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
    let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}});

You can see the dummy2 and dummy as a github repository here.I’m not sure where I went wrong and why this message is occuring. Please help me.

Thanks,
Nittin

Ok so there are two ways depending on what you are actually trying to do, but I suspect what you may want to do is to have the iframe sandboxed from the parent frame. And you do it by simply adding “sandbox” attribute to iframe, in the simplest form change:

<iframe src="...

to

<iframe sandbox src="...

@hubertlepicki I tried using the sandbox attribute. It solved the issue of constant reloading but I wasn’t able to submit a form. So, I gave sandbox="allow-scripts allow-forms" and it landed me to the same position I was earlier in.

okay, so I suspect this is a synthetic example of what you’ll have deployed somewhere else and you will only control the iframe content in the future? Because if not, you could also align the session options in both endpoints to share the same key / salt, and that would work too.

I also wonder if that’s because these are different and yet the domain is the same, i.e. localhost in both cases.

If that’s not going to be the case in your production system that you are working this out, i.e. the domains will differ, maybe you should make it in your dev environment to differ as well and maybe it’ll work because the cookies will no longer be automatically shared?
Try editing your hosts file (https://www.howtogeek.com/howto/27350/beginner-geek-how-to-edit-your-hosts-file/) so that you have two domains pointing to 127.0.0.1. Make it for example dummy.local and dymmy2.local and see if you can embed the iframe using the different domain you’re using.

I haven’t tried that but my hunch is that this is both in line with what you’re trying to do in real life, and may just work out of the box.

Might be useful: Phoenix LiveView in an iframe - #8 by cs44

1 Like

@hubertlepicki Thanks for the response. I’d like to tell you that this is not a synthetic example and it’s pretty much a commenting platform like Disqus where the application is embedded in an iframe. I don’t understand why the cookies will be automatically shared when both are actually two different domains. From your suggestion, I tried changing the host name and it actually worked in Chrome but resulted in me being in the same place I was earlier when I tried it in Safari.

Thanks for your response @ruslandoga. It worked well when I tried it but I’m looking for a solution with cross-browser compatibility.