2
votes

Background information: We have a platform which runs on https://system.example.com. This platform consists of 10 separate web applications (all written in PHP and JS). Each application has historically been in a sub-directory within the same subdomain:

  • https://system.example.com/app1/
  • https://system.example.com/app2/
  • ...
  • https://system.example.com/app10/

We are in the process of rebuilding one of the applications, app2, and have decided to host this on a new separate subdomain, https://app2.example.com.

Part of the app2 application uses JavaScript to open a pop-up window for app10. Most functionality inside this popup works as expected. However, when attempting to use a "Save" button inside the popup my browser console was showing:

Uncaught DOMException: Blocked a frame with origin "https://app2.example.com" from accessing a cross-origin frame. at https://system.example.com/app10/manage.php:1:334

I have read both SecurityError: Blocked a frame with origin from accessing a cross-origin frame and https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage but still unclear as to how to fix this.

The code and process I have is as follows:

The popup is opened from https://app2.example.com by a button which has an onclick event handler:

<button onclick="postToPopUp('https://system.example.com/app10/manage.php', 'fileManage', 'width=800px,height=600px', ['f_id', '123'], 'app2', 'filesCallbackManage')">Open app10</button>

The postToPopup() function is used to pass POST data from app2 into https://system.example.com/app10/manage.php based on Javascript window.open pass values using POST - this works fine.

The problem occurs when I click a "Save" button inside the popup which renders the following markup within the popup window:

<!doctype HTML><html><head><title>upload</title>
<script type="text/javascript" language="javascript" charset="utf-8">
var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);
window.close();
</script><body></body></html>

What this did originally - when everything was under the same subdomain - was called a js function filesCallbackManage() which resided in the code for https://system.example.com/app2. The function itself was passed an object, fileObject, which updated various parts of the UI inside app2. The popup was closed after clicking the Save button due to window.close();

Although I've read about using postMessage I don't understand how this fits in or whether this is even the correct solution to my problem? The data is being posted from the subdomain https://app2.example.com to https://system.example.com/app10 correctly. The problem is that filesCallbackManage() won't fire because of the cross origin restriction. Inside my code for https://app2.example.com I have a simple statement to see if it's firing:

function filesCallbackManage(data)
{
    console.log('filesCallbackManage has fired');
}

This never fires because of the problem I have. I get the console error mentioned previously and a blank popup window (technically this is correct since there is nothing in the <body> tag in the above markup) but the window doesn't close and the callback isn't fired.

The example given on the Mozilla website isn't extensive enough to understand how it can be adapted to this type of scenario. Please can someone elaborate? Furthermore, the linked Stack Overflow post is four years old so I want to be sure anything I put on this is secure and up-to-date.

1

1 Answers

0
votes

The postToPopup() function is used to pass POST data

Submitting a form across origins is fine. So you can do this.

The problem occurs when I click a "Save" button inside the popup

You're trying to access the DOM of the window across origins. This is forbidden.

Although I've read about using postMessage I don't understand how this fits in or whether this is even the correct solution to my problem?

postMessage is as close as you can get to accessing the DOM of a window across origins.

You can't do this.

var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);

Instead you have to send a message:

window.opener.postMessage(fileObject, "https://system.example.com");

And have code which listens for it:

addEventListener("message", receiveMessage);

function receiveMessage(event) {
    if (event.origin !== "http://app2.example.com") { return false; }
    filesCallbackManage(event.data);
}