6

I've lightning component where I'm going to embed a visualforce page, and then there will be communication between these two windows via postMessage API. the problem is how will I get the VF page along with abslute url (including hostname) like https://mycustomdomain--c.visualforce.com/apex/managedPackageNS__VfPage

I tried several ways but there is no full proof way which provide a robust solution which should work in different cases. first it will be part of managed package so we cannot hardcode VF page URL and second we need the URL in any case because first of all we need it to pass into iframe src and second PostMessage targetorigin to ensure secure and valid communication. On visulforce side, the host name change based on namespace, without namespace, domain, without domain and sometime I see some cases where visualforce.com url is became, visual.force.com.

I'm trying to do what is mentioned in below post, the only change is URL will be dynamically constructed at both sides (Lightning and VF).
https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html

I'm open for other alternative suggestions as well through which I can validate the origin of the message to prevent any miscommunication.

0
+50

I've solved this in the following way, which seems to cover most bases. I've assumed that my domain is enabled for customers, because otherwise lightning components are not usable.

The main issue I think you are having is this critical update, which removes the pod from visualforce (and other) hostnames, and is responsible for the change from visual.force.com to visualforce.com.

To handle this, you have two options:

  1. Instruct all of your customers to enable the critical update (which will be done 19/10/2019 anyway.)

  2. Generate both the old and new format hostnames, send messages to both, and check messages coming in are from one or the other. To be very clear - I've not reviewed this approach with Salesforce's security review team - you might want to validate it with them, but in my mind it's sane because both domains will contain the same pages under package control.

Posting a message to a hostname which is not present in the iframe presents a message in the console in chrome, but no errors.

    public ProxyController() {
        String hostname = Url.getSalesforceBaseUrl().getHost();
        String myDomain = hostname.split('\\.')[0];
        if(myDomain.contains('--')) {
            //uses lastIndex to exclude namespace but include sandbox names
            // e.g. https://mydomain--sandbox--namespace.visualforce.com
            // and https://mydomain--namespace.visualforce.com
            myDomain = myDomain.substring(0, hostname.lastIndexOf('--'));
        }
        lcBaseURL = 'https://' + myDomain + '.lightning.force.com';
        Map<String, String> headers = ApexPages.currentPage().getHeaders();
        headers.put('X-Frame-Options', 'ALLOW-FROM ' + lcBaseURL);
        headers.put('Content-Security-Policy', 'frame-ancestors ' + lcBaseURL);
    }

    @AuraEnabled
    public static List<String> getVFBaseURL() {
        String hostname = Url.getSalesforceBaseUrl().getHost();
        // will support prod and sandboxes
        // e.g. https://mydomain--sandbox.lightning.force.com
            // and https://mydomain.lightning.force.com
        String myDomain = hostname.split('\\.')[0];
        String namespace = ProxyController.class.getName().split('\\.')[0];
        String pod = [SELECT InstanceName FROM Organization].InstanceName.toLowerCase();
        return new List<String>{
                'https://' + myDomain + '--' + namespace + '.visualforce.com',
                'https://' + myDomain + '--' + namespace + '.' + pod + '.visual.force.com'
        };
    }

One warning - we could not get iframing to work reliably in Safari or Salesforce Mobile on ios, so did not use this mechanism in our managed package in the end. I've posted a question about it, but not made much progress in understanding the problem nor resolving it. This approach worked successfully for us in Chrome / Edge / Firefox and Salesforce Mobile on Android.

  • somehow I wanted to avoid multiple post-messages but I don't think so there is any other way to handle it, one more thing which rely on dynamic VF page is setting iframe source (src) which should load the page, currently we are using relative URL rather then absolute URL, like /apex/<managed_package_NS>__pageName?<param> but again it's not valid approach it will get caught in Security review. what you suggests should I load two VF frames as well as per the hostname change. – user2809299 Jan 15 at 6:26
  • Have you had a submission rejected in security review because you've used a relative URL? Are your page name and namespace static? What was Salesforce's justification for not using a relative URL? – James Jan 15 at 9:31
  • 1
    Well I read it about from a SF dev blog post, https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html as per this post you should pass hostname with https protocol to embed the URL, because that's what mentioned in https://developer.salesforce.com/docs/atlas.en-us.secure_coding_guide.meta/secure_coding_guide/secure_coding_lightning_security.htm#Cross_Site_Scripting – user2809299 Jan 16 at 5:22
  • I believe I need to add false positive document with the scan report to justify this. – user2809299 Jan 16 at 5:23
  • You might want to book a security review office hours session to check this. A false positive document normally references an issue found in a code scanner which I don't think is the case here. I'd use the relative URL, as you already know you're in a secure Salesforce page, and then you are relying on Salesforce to redirect you to the appropriate domain securely. As long as you are not generating the URL from user input I think this is fine, but I'd love to know if I'm wrong. – James Jan 16 at 10:25

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.