Using window.postMessage to post messages between windows & iframes

May 12, 2017 Off By Manish Kumar

HTML5PostMessage

Using postMessage, a new feature in HTML5 to securely communicate between parent and child window, to post messages between windows & iframes.

The Window.postMessage() method safely enables cross-origin communication. Normally, scripts on different pages are allowed to access each other if and only if the pages that executed them are at locations with the same protocol (usually both https), port number (443 being the default for https), and host (modulo Document.domain being set by both pages to the same value). window.postMessage() provides a controlled mechanism to circumvent this restriction in a way which is secure when properly used.

The window.postMessage() method, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g., remaining event handlers if window.postMessage() is called from an event handler, previously-set pending timeouts, etc.) The MessageEvent has the type message, a data property which is set to the value of the first argument provided to window.postMessage(), an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage() was called, and a source property which is the window from which window.postMessage() is called. (Other standard properties of events are present with their expected values.)

Here in this post I created two applications:

  1. EAApp
  2. iFrameApp

This will demonstrate how securely enclosing application and iFrame application post messages to each other using window.postMessage feature.

Parent/Enclosing App

HTML
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ"
crossorigin="anonymous">
<script src="app.js"></script>
</head>

<body>
<div class="container">
<h1>Enclosing app</h1>
<div class="row">
<p id="iframereceived-message">I've heard nothing yet from iFrame</p>
</div>
<div class="row">
<form id="the-form" action="/">
<div class="form-group">
<input type="text" class="form-control" id="my-message" value="Your message">
</div>
<div class="form-group">
<input type="submit" class="btn btn-default" value="postMessage">
</div>

</form>
</div>
<div class="row">
<iframe id="da-iframe" height="300px" width="400px" src="http://localhost:8091/iFrameApp/postMessageTarget.html"></iframe>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn"
crossorigin="anonymous"></script>
</body>

</html>
JavaScript code:
window.onload = function () {
var iframeWin = document.getElementById("da-iframe").contentWindow,
form = document.getElementById("the-form"),
myMessage = document.getElementById("my-message");

myMessage.select();

form.onsubmit = function () {
iframeWin.postMessage(myMessage.value, "http://localhost:8091/");
return false;
};

};

if (window.addEventListener) {
// For standards-compliant web browsers
window.addEventListener("message", displayiFrameMessage, false);
}
else {
window.attachEvent("onmessage", displayiFrameMessage);
}

function displayiFrameMessage (e) {
var messageFromIFrame;
if (e.origin !== "http://localhost:8091") {
messageFromIFrame = "You are not worthy iframe";
}
else {
messageFromIFrame = "Message from iFrame:" + e.data + "
Origin: " + e.origin;
}
document.getElementById("iframereceived-message").innerHTML = messageFromIFrame;
}

iFrame App

HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

</head>
<body>
<div class="container">
<div class="row">
<p id="received-message">I've heard nothing yet</p>
</div>
<div class="row">
<form id="iframe-form" action="/">
<div class="form-group">
<input type="text" class="form-control" id="framemy-message" value="ifrmae message">
</div>
<div class="form-group">
<input type="submit" class="btn btn-default" value="postMessage">
</div>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="frame.js"></script>
</body>
</html>
JavaScript code
var EAWindow;
function displayMessage (evt) {
var message;
EAWindow = evt;
if (evt.origin !== "http://localhost:8092") {
message = "You are not worthy";
}
else {
message = "Message from EA: " + evt.data + "
Origin: " + evt.origin;
}
document.getElementById("received-message").innerHTML = message;

}
if (window.addEventListener) {
// For standards-compliant web browsers
window.addEventListener("message", displayMessage, false);
}
else {
window.attachEvent("onmessage", displayMessage);
}
var iframeform = document.getElementById("iframe-form");
iframeform.onsubmit = function () {
var myMessageToEA = document.getElementById("framemy-message");
myMessageToEA.select();
EAWindow.source.postMessage(myMessageToEA.value, "http://localhost:8092/");
return false;
};

Output

References
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

You can download this sample app from my github repository: HTML5PostMessage