You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

@turnkey/iframe-stamper

Package Overview
Dependencies
Maintainers
8
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@turnkey/iframe-stamper - npm Package Compare versions

Comparing version

to
2.2.0

156

./dist/index.js

@@ -67,2 +67,5 @@ 'use strict';

})(exports.KeyFormat || (exports.KeyFormat = {}));
function generateUUID() {
return crypto.randomUUID();
}
/**

@@ -108,3 +111,38 @@ * Stamper to use with `@turnkey/http`'s `TurnkeyClient`

this.messageChannel = new MessageChannel();
// Initialize a pending requests tracker
this.pendingRequests = new Map();
}
onMessageHandler(event) {
const { type, value, requestId } = event.data || {};
// Handle messages without requestId (like PUBLIC_KEY_READY)
if (!requestId) {
if (type === exports.IframeEventType.PublicKeyReady) {
this.iframePublicKey = value;
return;
}
return;
}
const pendingRequest = this.pendingRequests.get(requestId);
if (!pendingRequest) {
console.warn(`Received response for unknown request: ${requestId}`);
return;
}
// Remove from pending requests
this.pendingRequests.delete(requestId);
if (type === exports.IframeEventType.Error) {
pendingRequest.reject(new Error(value));
return;
}
// Handle specific response types
switch (type) {
case exports.IframeEventType.Stamp:
pendingRequest.resolve({
stampHeaderName,
stampHeaderValue: value,
});
break;
default:
pendingRequest.resolve(value);
}
}
/**

@@ -114,28 +152,19 @@ * Inserts the iframe on the page and returns a promise resolving to the iframe's public key

async init() {
this.container.appendChild(this.iframe);
/**
* Once the iframe is loaded, we send a message to the iframe to hand over the
* MessageChannel's second port, port2, and establish the secure communication channel.
* The iframe will use this port to send messages back to the parent page.
* See https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage#transfer
*/
this.iframe.addEventListener("load", () => {
if (!this.iframe.contentWindow ||
!this.iframe.contentWindow.postMessage) {
throw new Error("contentWindow or contentWindow.postMessage does not exist");
}
this.iframe.contentWindow.postMessage({ type: exports.IframeEventType.TurnkeyInitMessageChannel }, this.iframeOrigin, [this.messageChannel.port2]);
});
return new Promise((resolve, _reject) => {
/**
* The MessageChannel port1 property is the port that gets attached
* to the context that instantiated the MessageChannel. This class, the IframeStamper,
* instantied the MessageChannel and will use port1 to send messages to the iframe.
* See https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel/port1
*/
return new Promise((resolve, reject) => {
this.container.appendChild(this.iframe);
this.iframe.addEventListener("load", () => {
if (!this.iframe.contentWindow?.postMessage) {
reject(new Error("contentWindow or contentWindow.postMessage does not exist"));
return;
}
this.iframe.contentWindow.postMessage({ type: exports.IframeEventType.TurnkeyInitMessageChannel }, this.iframeOrigin, [this.messageChannel.port2]);
});
this.messageChannel.port1.onmessage = (event) => {
// Handle initial PublicKeyReady event
if (event.data?.type === exports.IframeEventType.PublicKeyReady) {
this.iframePublicKey = event.data["value"];
resolve(event.data["value"]);
this.iframePublicKey = event.data.value;
resolve(event.data.value);
}
// Handle all other messages
this.onMessageHandler(event);
};

@@ -151,2 +180,3 @@ });

this.iframe.remove();
this.pendingRequests.clear();
}

@@ -160,26 +190,22 @@ /**

/**
* Adds a message handler to the iframe's message channel
* Generic function to abstract away request creation
* @param type
* @param payload
* @returns expected shape <T>
*/
addMessageHandler() {
createRequest(type, payload = {}) {
return new Promise((resolve, reject) => {
this.messageChannel.port1.onmessage = (event) => {
this.onMessageHandler(event, resolve, reject);
};
const requestId = generateUUID();
this.pendingRequests.set(requestId, {
resolve,
reject,
requestId,
});
this.messageChannel.port1.postMessage({
type,
requestId,
...payload,
});
});
}
onMessageHandler(event, resolve, reject) {
switch (event.data?.type) {
case exports.IframeEventType.Stamp:
resolve({
stampHeaderName: stampHeaderName,
stampHeaderValue: event.data["value"],
});
break;
case exports.IframeEventType.Error:
reject(event.data["value"]);
break;
default:
resolve(event.data["value"]);
}
}
/**

@@ -192,10 +218,4 @@ * Function to inject a new credential into the iframe

async injectCredentialBundle(bundle) {
return new Promise((resolve, reject) => {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectCredentialBundle,
value: bundle,
});
this.messageChannel.port1.onmessage = (event) => {
this.onMessageHandler(event, resolve, reject);
};
return this.createRequest(exports.IframeEventType.InjectCredentialBundle, {
value: bundle,
});

@@ -211,4 +231,3 @@ }

async injectKeyExportBundle(bundle, organizationId, keyFormat) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectKeyExportBundle,
return this.createRequest(exports.IframeEventType.InjectKeyExportBundle, {
value: bundle,

@@ -218,3 +237,2 @@ keyFormat,

});
return this.addMessageHandler();
}

@@ -228,8 +246,6 @@ /**

async injectWalletExportBundle(bundle, organizationId) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectWalletExportBundle,
return this.createRequest(exports.IframeEventType.InjectWalletExportBundle, {
value: bundle,
organizationId,
});
return this.addMessageHandler();
}

@@ -241,4 +257,3 @@ /**

async injectImportBundle(bundle, organizationId, userId) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectImportBundle,
return this.createRequest(exports.IframeEventType.InjectImportBundle, {
value: bundle,

@@ -248,3 +263,2 @@ organizationId,

});
return this.addMessageHandler();
}

@@ -258,6 +272,3 @@ /**

async extractWalletEncryptedBundle() {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ExtractWalletEncryptedBundle,
});
return this.addMessageHandler();
return this.createRequest(exports.IframeEventType.ExtractWalletEncryptedBundle);
}

@@ -272,7 +283,3 @@ /**

async extractKeyEncryptedBundle(keyFormat) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ExtractKeyEncryptedBundle,
keyFormat: keyFormat,
});
return this.addMessageHandler();
return this.createRequest(exports.IframeEventType.ExtractKeyEncryptedBundle, { keyFormat });
}

@@ -284,8 +291,5 @@ /**

async applySettings(settings) {
const settingsStr = JSON.stringify(settings);
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ApplySettings,
value: settingsStr,
return this.createRequest(exports.IframeEventType.ApplySettings, {
value: JSON.stringify(settings),
});
return this.addMessageHandler();
}

@@ -299,7 +303,5 @@ /**

}
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.StampRequest,
return this.createRequest(exports.IframeEventType.StampRequest, {
value: payload,
});
return this.addMessageHandler();
}

@@ -306,0 +308,0 @@ }

# @turnkey/iframe-stamper
## 2.2.0
### Minor Changes
- a216a47: Add request ID to iframe requests
## 2.1.0

@@ -4,0 +10,0 @@

@@ -68,2 +68,3 @@ /// <reference lib="dom" />

messageChannel: MessageChannel;
private pendingRequests;
/**

@@ -74,2 +75,3 @@ * Creates a new iframe stamper. This function _does not_ insert the iframe in the DOM.

constructor(config: TIframeStamperConfig);
onMessageHandler(event: MessageEvent): void;
/**

@@ -88,6 +90,8 @@ * Inserts the iframe on the page and returns a promise resolving to the iframe's public key

/**
* Adds a message handler to the iframe's message channel
* Generic function to abstract away request creation
* @param type
* @param payload
* @returns expected shape <T>
*/
addMessageHandler(): Promise<any>;
onMessageHandler(event: MessageEvent, resolve: any, reject: any): void;
private createRequest;
/**

@@ -94,0 +98,0 @@ * Function to inject a new credential into the iframe

@@ -67,2 +67,5 @@ 'use strict';

})(exports.KeyFormat || (exports.KeyFormat = {}));
function generateUUID() {
return crypto.randomUUID();
}
/**

@@ -108,3 +111,38 @@ * Stamper to use with `@turnkey/http`'s `TurnkeyClient`

this.messageChannel = new MessageChannel();
// Initialize a pending requests tracker
this.pendingRequests = new Map();
}
onMessageHandler(event) {
const { type, value, requestId } = event.data || {};
// Handle messages without requestId (like PUBLIC_KEY_READY)
if (!requestId) {
if (type === exports.IframeEventType.PublicKeyReady) {
this.iframePublicKey = value;
return;
}
return;
}
const pendingRequest = this.pendingRequests.get(requestId);
if (!pendingRequest) {
console.warn(`Received response for unknown request: ${requestId}`);
return;
}
// Remove from pending requests
this.pendingRequests.delete(requestId);
if (type === exports.IframeEventType.Error) {
pendingRequest.reject(new Error(value));
return;
}
// Handle specific response types
switch (type) {
case exports.IframeEventType.Stamp:
pendingRequest.resolve({
stampHeaderName,
stampHeaderValue: value,
});
break;
default:
pendingRequest.resolve(value);
}
}
/**

@@ -114,28 +152,19 @@ * Inserts the iframe on the page and returns a promise resolving to the iframe's public key

async init() {
this.container.appendChild(this.iframe);
/**
* Once the iframe is loaded, we send a message to the iframe to hand over the
* MessageChannel's second port, port2, and establish the secure communication channel.
* The iframe will use this port to send messages back to the parent page.
* See https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage#transfer
*/
this.iframe.addEventListener("load", () => {
if (!this.iframe.contentWindow ||
!this.iframe.contentWindow.postMessage) {
throw new Error("contentWindow or contentWindow.postMessage does not exist");
}
this.iframe.contentWindow.postMessage({ type: exports.IframeEventType.TurnkeyInitMessageChannel }, this.iframeOrigin, [this.messageChannel.port2]);
});
return new Promise((resolve, _reject) => {
/**
* The MessageChannel port1 property is the port that gets attached
* to the context that instantiated the MessageChannel. This class, the IframeStamper,
* instantied the MessageChannel and will use port1 to send messages to the iframe.
* See https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel/port1
*/
return new Promise((resolve, reject) => {
this.container.appendChild(this.iframe);
this.iframe.addEventListener("load", () => {
if (!this.iframe.contentWindow?.postMessage) {
reject(new Error("contentWindow or contentWindow.postMessage does not exist"));
return;
}
this.iframe.contentWindow.postMessage({ type: exports.IframeEventType.TurnkeyInitMessageChannel }, this.iframeOrigin, [this.messageChannel.port2]);
});
this.messageChannel.port1.onmessage = (event) => {
// Handle initial PublicKeyReady event
if (event.data?.type === exports.IframeEventType.PublicKeyReady) {
this.iframePublicKey = event.data["value"];
resolve(event.data["value"]);
this.iframePublicKey = event.data.value;
resolve(event.data.value);
}
// Handle all other messages
this.onMessageHandler(event);
};

@@ -151,2 +180,3 @@ });

this.iframe.remove();
this.pendingRequests.clear();
}

@@ -160,26 +190,22 @@ /**

/**
* Adds a message handler to the iframe's message channel
* Generic function to abstract away request creation
* @param type
* @param payload
* @returns expected shape <T>
*/
addMessageHandler() {
createRequest(type, payload = {}) {
return new Promise((resolve, reject) => {
this.messageChannel.port1.onmessage = (event) => {
this.onMessageHandler(event, resolve, reject);
};
const requestId = generateUUID();
this.pendingRequests.set(requestId, {
resolve,
reject,
requestId,
});
this.messageChannel.port1.postMessage({
type,
requestId,
...payload,
});
});
}
onMessageHandler(event, resolve, reject) {
switch (event.data?.type) {
case exports.IframeEventType.Stamp:
resolve({
stampHeaderName: stampHeaderName,
stampHeaderValue: event.data["value"],
});
break;
case exports.IframeEventType.Error:
reject(event.data["value"]);
break;
default:
resolve(event.data["value"]);
}
}
/**

@@ -192,10 +218,4 @@ * Function to inject a new credential into the iframe

async injectCredentialBundle(bundle) {
return new Promise((resolve, reject) => {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectCredentialBundle,
value: bundle,
});
this.messageChannel.port1.onmessage = (event) => {
this.onMessageHandler(event, resolve, reject);
};
return this.createRequest(exports.IframeEventType.InjectCredentialBundle, {
value: bundle,
});

@@ -211,4 +231,3 @@ }

async injectKeyExportBundle(bundle, organizationId, keyFormat) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectKeyExportBundle,
return this.createRequest(exports.IframeEventType.InjectKeyExportBundle, {
value: bundle,

@@ -218,3 +237,2 @@ keyFormat,

});
return this.addMessageHandler();
}

@@ -228,8 +246,6 @@ /**

async injectWalletExportBundle(bundle, organizationId) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectWalletExportBundle,
return this.createRequest(exports.IframeEventType.InjectWalletExportBundle, {
value: bundle,
organizationId,
});
return this.addMessageHandler();
}

@@ -241,4 +257,3 @@ /**

async injectImportBundle(bundle, organizationId, userId) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.InjectImportBundle,
return this.createRequest(exports.IframeEventType.InjectImportBundle, {
value: bundle,

@@ -248,3 +263,2 @@ organizationId,

});
return this.addMessageHandler();
}

@@ -258,6 +272,3 @@ /**

async extractWalletEncryptedBundle() {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ExtractWalletEncryptedBundle,
});
return this.addMessageHandler();
return this.createRequest(exports.IframeEventType.ExtractWalletEncryptedBundle);
}

@@ -272,7 +283,3 @@ /**

async extractKeyEncryptedBundle(keyFormat) {
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ExtractKeyEncryptedBundle,
keyFormat: keyFormat,
});
return this.addMessageHandler();
return this.createRequest(exports.IframeEventType.ExtractKeyEncryptedBundle, { keyFormat });
}

@@ -284,8 +291,5 @@ /**

async applySettings(settings) {
const settingsStr = JSON.stringify(settings);
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.ApplySettings,
value: settingsStr,
return this.createRequest(exports.IframeEventType.ApplySettings, {
value: JSON.stringify(settings),
});
return this.addMessageHandler();
}

@@ -299,7 +303,5 @@ /**

}
this.messageChannel.port1.postMessage({
type: exports.IframeEventType.StampRequest,
return this.createRequest(exports.IframeEventType.StampRequest, {
value: payload,
});
return this.addMessageHandler();
}

@@ -306,0 +308,0 @@ }

{
"name": "@turnkey/iframe-stamper",
"version": "2.1.0",
"version": "2.2.0",
"main": "./dist/index.js",

@@ -5,0 +5,0 @@ "module": "./dist/index.mjs",

@@ -33,3 +33,3 @@ # @turnkey/iframe-stamper

{ baseUrl: "https://api.turnkey.com" },
iframeStamper
iframeStamper,
);

@@ -36,0 +36,0 @@ ```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet