3

Following this example: https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html

I am able to communicate between an LWC and a VisualForce page in an embedded iframe. BUT only when I know the URLs of both the LWC and VF page in advance, furthermore, these URLs often follow different conventions in community etc.

How can I create multiple LWCs that each have single iframe containing a (universal) VF page, where each LWC knows the origin that the VF page is expecting and the VF page knows the origin that the LWC is expecting.

Code:

testLC.js

export default class TestLC extends LightningElement {
    //iFrameUrl = 'https://communityorscratchorg.lightning.force.com/apex/testVF';
    iFrameUrl = window.location.origin + '/apex/testVF';

    vfOrigin = 'https://communityorscratchorg--namespace.visualforce.com';

    renderedCallback() {
        window.addEventListener('message', event => {
            if (event.origin !== this.vfOrigin) {
                console.log('VF has received an unknown message');
                return;
            }
            console.log('LC has received a message from VF');
        }, false);
    }

    sendToVF(event) {
        //console.log(window.location.host); // communityorscratchorg.lightning.force.com
        //console.log(window.location.hostname); // communityorscratchorg.lightning.force.com
        //console.log(window.location.href); // https://communityorscratchorg.lightning.force.com/lightning/page/home
        //console.log(window.location.origin); // https://communityorscratchorg.lightning.force.com
        //console.log(window.location.pathname); // lightning/page/home
        let iframe = this.template.querySelector('iframe');
        iframe.contentWindow.postMessage('test send to VF from LC', this.vfOrigin);
    }
}

testVF.page

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0" >
<script>
    let lwcOrigin = 'https://communityorscratchorg.lightning.force.com';

        window.addEventListener('message', event => {
        if (event.origin !== lwcOrigin) {
            console.log('VF has received an unknown message');
                return;
            }
            console.log('VF has received a message from LC');
        }, false);

        function sendToLC(event) {
            //console.log(window.location.host); // communityorscratchorg--namespace.visualforce.com
            //console.log(window.location.hostname); // communityorscratchorg--namespace.visualforce.com
            //console.log(window.location.href); // https://communityorscratchorg--namespace.visualforce.com/apex/testVF
            //console.log(window.location.origin); // https://communityorscratchorg--namespace.visualforce.com
            //console.log(window.location.pathname); // /apex/testVF
            parent.postMessage('test send to LC from VF', lwcOrigin);
        }
    </script>
    <body>
        <div>
            Test VF Page.
        </div>
        <div>
            <button onclick="sendToLC()">Send To LC</button>
       </div>
    </body>
</apex:page>

Notice how the naming convention of the URLs appear in the OTHER page/component from which they must be assessed.

EDIT: I have discovered that sending a message with a "*" as the targetOrigin, like this:

let iframe = this.template.querySelector('iframe');
iframe.contentWindow.postMessage('test send to VF from LC', '*');

Or

parent.postMessage('test send to LC from VF', '*');

Allows the message to be sent to the receiving page (unlike if an undefined or invalid URL was given), and the receiving pages event listener seems to populate the event parameter with the correct origin that is checked by the receiving page.

This may be a security concern (I do not know if this happens with "hacker-scenario" type domain crossing). But it may be sufficient to implement your own handshake security token or server-generated one time user/session token to validate these LWC/VF iframe messages.

1
  • I haven't tested with LWC, but I know that in my own testing I have found that within communities specifically both Aura components and Visualforce pages will return the same window.location.protocol and window.location.host, which you can then use to verify the origin. I think that is not the case in lightning experience though.
    – Kyle
    Oct 10 '19 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.