javascriptcross-domainpostmessagemultiple-domains

Javascript window.opener.postMessage Cross Origin with multiple sub domains


I'm trying to allow multiple subdomains when doing :

window.opener.postMessage(...);

This works but this is not safe as all possible domains are allowed and I don't want this :

window.opener.postMessage('MyMSG', '*');

This works for a single domain :

window.opener.postMessage('MyMSG', 'https://example.com');

But what if I want to allow this : *.example.com ?

Of course this:

window.opener.postMessage('MyMSG', '*.example.com');
window.opener.postMessage('MyMSG', 'https://*.example.com');
window.opener.postMessage('MyMSG', 'https://(.*)example.com');

does not works

What is the right way to do that? Is that even possible?

Thank you


Solution

  • The targetOrigin expects * or an exact uri, ie no subdomain wildcards.

    If you want to post to multiple targets than you will need a separate postMessage() call for each. To make this easier you can just put all the domains into a list and iterate over the list instead of hard-coding each call.

    var someData = {};
    var subdomains = ["one","two","three"];
    for(var subdomain of subdomains){
      let target = "http://"+subdomain+".example.com"
      window.postMessage(someData,target);
    }
    

    But this come with maintenance cost of keeping the list updated

    Now depending on which end your code is at you can also use certain methods to get an exact uri at runtime. Note examples use URL to parse out just the protocol and host to get a proper value to pass to postMessage.

    If you are on the end that opened a window, or the parent of iframe, you can just grab the src,href, or whatever property used to indicate the url for the window, iframe, etc.

    //if using for instance window.open()
    //you already know the url as it has to be passed to the function
    var target = window.open("http://example.com/some/path");
    
    //so in this case you would first save the url to a variable and use that variable for both
    var url = new URL("http://example.com/some/path");
    var targetDomain = url.protocol + "//" + url.host;
    
    var target = window.open(url.href);
    target.postMessage("message",targetDomain);
    
    //if using an iframe just grab the src property and parse the domain from that
    var url = new URL(iframeElement.src);
    var targetDomain = url.protocol+"//"+url.host;
    iframeElement.contentWindow.postMessage("message",targetDomain);
    

    Now if you are on the other side, ie in the iframe or the opened window you can use document.referrer with the exception when opening a non-secure url from a secure page. Meaning document.referrer won't be set when you open a http:// url when your page is using https://

    var url = new URL( document.referrer );
    var target = url.protocol+"//"+url.host;
    //opened window
    window.opener.postMessage("message",target);
    //iframe
    window.parent.postMessage("message",target);