Iframes and the postMessage Method

JavaScript can be used to communicate between documents when using iframes, as discussed at Iframes and Cross-Document Communication. However, if the documents are not on the same domain, the same-origin policy prevents access to most objects and properties and will trigger access denied errors when JavaScript attempts communication.

Cross-Document Messaging with postMessage is designed to provide a safe means of communication between documents on different domains while still offering protection from cross-site scripting attacks. This method can be used with iframes as well as between windows when the window.open method is used by one to open another.

How to Use postMessage

There are two basic components to cross-document messaging: the postMessage method invocation, and the onmessage event handler set up in the receiving document to respond to incoming messages.

To send a message from one document to another, begin by obtaining a reference to the window you want to send a message to. If sending a message to a document in an iframe, first get a reference to the iframe and then its contentWindow property as shown below. If sending a message from the iframed document to the containing document, the parent keyword provides a reference.

If sending a message to a window opened using the window.open method, a reference is returned from the method. If sending a message from a window opened using the window.open method, the opener property of the window provides that reference.

postMessage Arguments

The postMessage method takes two arguments: the message to be sent (data), and the domain to which you wish to send it (formally referred to as the target origin):

// get reference to window inside the iframe
var wn = document.getElementById('ifrm').contentWindow;
// postMessage arguments: data to send, target origin
wn.postMessage('Hello to iframe from parent!', 'http://www.example.com');

The postMessage method supports data types including strings, numbers, arrays, and objects. The target origin argument includes the protocol, host, and optionally, the port of the document to receive the message. Target origin can also be specified using an "*" (any origin) or "/" (the same origin as the document sending the message). If the origin of the target window doesn't match the specified origin, the message is not sent.

The Message Event

When a message is sent using postMessage, a message event is fired on the destination window. In order to process the event, you need a message event handler. You can use addEventListener to assign a handler for the message event, or you can assign a function to the onmessage property of the window object.

window.addEventListener('message', handleMessage, false);

An event object is passed to the message event handler. The message event includes the following properties:

data
the message being sent
origin
the origin of the document that sent the message (protocol, hostname, and possibly port)
source
a reference to the window object from which the message came

The following message event handler function demonstrates how these properties can be used:

// message event handler (e is event object) 
function handleMessage(e) {
    // Reference to element for data display
    var el = document.getElementById('display');
    // Check origin
    if ( e.origin === 'http://www.example.com' ) {
        // Retrieve data sent in postMessage
        el.innerHTML = e.data;
        // Send reply to source of message
        e.source.postMessage('Message received', e.origin);
    }
}

Security Considerations

The postMessage specification recommends the following steps to ensure the safety of the process when using cross-document messaging:

  • Check the origin attribute to ensure that messages are only accepted from domains that you expect to receive messages from.
  • If you don't check the origin attribute and instead accept messages from any origin, keep in mind the potential risk for denial-of-service attacks. Controlling the number of messages accepted per minute could offer protection in this case.
  • Check the data received to be sure it is the type of data you are expecting.
  • Don't use the wildcard target origin ("*") when sending messages that contain confidential information.

Back to top