npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

secure-postmate

v1.0.9

Published

A powerful, simple, promise-based, secure postMessage library

Downloads

16

Readme

A powerful, simple, promise-based, secure postMessage library.

NPM NPM Build Status Code Climate License

Build Status

SecurePostmate is a promise-based API built on postMessage. It allows a parent page to speak with a child iFrame across origins with minimal effort. Cross-origin communication is secured by elliptic curve cryptography with dynamic key-pairs generation.


Features

  • Promise-based API for elegant and simple communication.
  • Secure two-way parent <-> child handshake, with message validation.
  • Child exposes a retrievable model object that the parent can access.
  • Child emits events that the parent can listen to.
  • Parent can call functions within a child.
  • ECC encryption using Stanford Javascript Crypto Library.

Installing

SecurePostmate can be installed via NPM.

NPM

$ yarn add secure-postmate # Install via Yarn
$ npm i secure-postmate --save # Install via NPM

Also you can download the compiled javascript directly here

Glossary

  • Parent: The top level page that will embed an iFrame, creating a Child.
  • Child: The bottom level page loaded within the iFrame.
  • Model: The object that the Child exposes to the Parent.
  • Handshake: The process by which the parent frame identifies itself to the child, and vice versa. When a handshake is complete, the two contexts have bound their event listeners and identified one another.

Usage

  1. The Parent begins communication with the Child. A handshake is sent, the Child responds with a handshake reply, finishing Parent/Child initialization. The two are bound and ready to communicate securely.

  2. The Parent fetches values from the Child by property name. The Child can emit messages to the parent. The Parent can call functions in the Child Model.


Example

parent.com

// Kick off the handshake with the iFrame
const handshake = new SecurePostmate({
  container: document.getElementById('some-div'), // Element to inject frame into
  url: 'http://child.com/page.html'
});

// When parent <-> child handshake is complete, data may be requested from the child
handshake.then(child => {

  // Fetch the height property in child.html and set it to the iFrames height
  child.get('height')
    .then(height => child.frame.style.height = `${height}px`);

  // Listen to a particular event from the child
  child.on('some-event', data => console.log(data)); // Logs "Hello, World!"
});

child.com/page.html

const handshake = new SecurePostmate.Model({
  // Expose your model to the Parent. Property values may be functions, promises, or regular values
  height: () => document.height || document.body.offsetHeight
});

// When parent <-> child handshake is complete, events may be emitted to the parent
handshake.then(parent => {
  parent.emit('some-event', 'Hello, World!');
});

API

Postmate.debug

// parent.com or child.com
SecurePostmate.debug = true;
new SecurePostmate(options);

Name | Type | Description | Default :--- | :--- | :--- | :--- debug | Boolean | Set to true to enable logging of additional information | false


Postmate(options)

// parent.com
new SecurePostmate({
  container: document.body,
  url: 'http://child.com/',
  model: { foo: 'bar' }
});

This is written in the parent page. Initiates a connection with the child. Returns a Promise that signals when the handshake is complete and communication is ready to begin.

Returns: Promise(child)

Properties

Name | Type | Description | Default :--- | :--- | :--- | :--- container (optional) | DOM Node Element | An element to append the iFrame to | document.body url | String | A URL to load in the iFrame. The origin of this URL will also be used for securing message transport | none model | Object | An object literal to represent the default values of the Childs model | none


Postmate.Model(model)

// child.com new SecurePostmate.Model({ // Serializable values foo: "bar",

// Functions height: () => document.height || document.body.offsetHeight,

// Promises data: fetch(new Request('data.json')) });

> This is written in the child page. Calling `Postmate.Model` initiates a handshake request listener from the `Parent`. Once the handshake is complete, an event listener is bound to receive requests from the `Parent`. The `Child` model is _extended_ from the `model` provided by the `Parent`.

#### Parameters

Name | Type | Description | Default
:--- | :--- | :--- | :---
**`model`** | `Object` | _An object of gettable properties to expose to the parent. Value types may be anything accepted in `postMessage`. Promises may also be set as values or returned from functions._ | `{}`

***

> ## `child.get(key)`
```javascript
// parent.com
new SecurePostmate({
  container: document.body,
  url: 'http://child.com/'
}).then(child => {
  child.get('something').then(value => console.log(value));
});

Retrieves a value by property name from the Childs model object.

Returns: Promise(value)

Parameters

Name | Type | Description :--- | :--- | :--- key | String (required) | The string property to lookup in the childs model


child.call(key, data)

// parent.com
new SecurePostmate({
  container: document.body,
  url: 'http://child.com/'
}).then(child => {
  child.call('sayHi', 'Hello, World!');
});

Calls the function sayHi in the Child Model with the parameter Hello, World!

Returns: undefined

Parameters

Name | Type | Description :--- | :--- | :--- key | String (required) | The string property to lookup in the childs model data | Mixed | The optional data to send to the child function


child.destroy()

// parent.com
new SecurePostmate({
  container: document.body,
  url: 'http://child.com/'
}).then(child => child.destroy());

Removes the iFrame element and destroys any message event listeners

Returns: undefined


##child.frame

new SecurePostmate(options).then(child => {
  child.get('height')
    .then(height => child.frame.style.height = `${height}px`);
});

The iFrame Element that the parent is communicating with

Troubleshooting/FAQ

General

Why use Promises for an evented API?

Promises provide a clear API for fetching data. Using an evented approach often starts backwards. if the parent wants to know the childs height, the child would need to alert the parent, whereas with SecurePostmate, the Parent will request that information from the child in a synchronous-like manner. The child can emit events to the parent as well, for those other use-cases that still need to be handled.

Silent Parent/Child

I've enabled logging but the parent or child is not logging everything.

SecurePostmate.debug needs to be set in both the parent and child for each of them to log their respective information

The child does not respond to communication from the Parent

Make sure that you have initialized SecurePostmate.Model in your child page.

Restrictive Communication

I want to retrieve information from the parent by the child

SecurePostmate (by design) is restrictive in its modes of communication. This enforces a simplistic approach: The parent is responsible for logic contained within the parent, and the child is responsible for logic contained within the child. If you need to retrieve information from parent -> child, consider setting a default model in the parent that the child may extend.

I want to send messages to the child from the parent

This is specifically what the call function is for.

Security

What is the Handshake and why do I need one?

By default, all message events received by any (parent) page can come from any (child) location. This means that the Parent must always enforce security within its message event, ensuring that the child (origin) is who we expect them to be, that the message is a response from an original request, and that our message is valid. The handshake routine solves this by saving the identities of the child and parent and ensuring that no changes are made to either.

How are messages validated?

The origin of the request, the message type, the postMessage mime-type, and in some cases the message response, are all verified against the original data made when the handshake was completed.

License

MIT