Front end communication

As mentioned before every plug-in instance is embedded into Haiilo Home via an HTML iFrame. To safely communicate between the parent site (i.e. the Haiilo Home front end) and the iFrame embedded within it, you can use the window.postMessage() method. Usually, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "same-origin policy"). window.postMessage() provides a controlled mechanism to securely circumvent this restriction (if used properly).

The receiver (both the plug-in as well as Haiilo Home itself) can listen for dispatched messages by registering a global message event listener.

Data format

While the data sent via window.postMessage() can be an arbitrary JavaScript object, Haiilo Home will only accept messages in a specific format that derives from RFC 7519 - JSON Web Token. It is important to adhere to this data format in order to successfully establish a communication to the Haiilo Home front end. Every message must thus incorporate the following properties:

AttributeTypeDescription
issstringThe issuer of the message - a unique identifier of the principal that issued the JWT.
substringThe subject of the message - one of several predefined topics that is the subject of the JWT.
jti stringA random nonce unique identifier for the JWT that is used to prevent the JWT from being replayed.

A message can hold additional payload on arbitrary attributes that don’t collide with the claim names above. Any message that does not comply with this format will be rejected by Haiilo Home. While Haiilo Home uses the current tenant’s URL for the issuer claim, a plug-in is provided with a unique source string in the invocation URL. This URL query parameter called src is to be used for the issuer claim so that Haiilo Home is able to identify the plug-in.

Secure communication

To secure the communication across different pages one should always specify the targetOrigin in a window.postMessage() call and the origin of the window that sent a message received via window.addEventListener.

Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the origin and possibly source properties. This cannot be overstated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.

MDN web docs

Haiilo Home will only sent messages to the URL defined in the plug-in manifest and will double check any received messages for this URL. This is to make sure that every message sent and received belongs to the respective plug-in.

📘

Hint

If you are using a middleware for your plugin, you can specify alternative targetOrigins using the origin field in your plugin manifest.

However, while Haiilo Home exactly knows where to find a plug-in via its accompanying manifest, the plug-in itself is in a slightly more difficult situation. Since every plug-in can be installed in a variety of different Haiilo Home environments (each one hosted under a different URL), it is hard to specify the targetOrigin for outgoing messages and check for the origin of incoming messages. This has a bunch of implications:

  • The plug-in needs to set the literal string "*" as the targetOrigin when sending messages to the Haiilo Home front end. Consequently, the plug-in cannot be fully certain that events are not disclosed to a malicious site. Thus, no highly confidential data must be sent this way. Instead, you might want to fall back to a back end to back end communication.

  • The plug-in must set the iss claim of the message to the unique identifier that is passed to the plug-in via the invocation URL. Haiilo Home automatically generates a unique random UUID and attach it to the URL as a src query parameter. The src property will not change over the lifetime of the plugin instance.

  • The plug-in is not able to check the origin of the event within callbacks of window.addEventListener. After all, the plug-in does not know where it is embedded. To establish a trustworthy communication from Haiilo Home to the plug-in, Haiilo Home will not send plain JSON data in response events. Instead, every Haiilo Home message is sent as a signed JSON Web Token. JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. You can read more about JWT and possible ways to decode a JWT at jwt.io.

Avoiding replay attacks

To prevent replay attacks, you should add a nonce to every message sent via the window.postMessage() API using the jti claim in outgoing messages. The definition of a nonce is optional, but Haiilo Home will place a randomly generated UUID in every message if a user-defined nonce is missing.

📘

Hint

You can also use the jti claim to add unique message IDs to your communication and thus allow for an unambiguous correlation between requests sent and responses received.