webcomponent: update CommandsManager to use targetIframeOrigin for improved security
This commit is contained in:
parent
738c7cb878
commit
1bdd968f79
@ -11,7 +11,15 @@ import { InboundCommandMessage } from '../models/message.type';
|
|||||||
*/
|
*/
|
||||||
export class CommandsManager {
|
export class CommandsManager {
|
||||||
private iframe: HTMLIFrameElement;
|
private iframe: HTMLIFrameElement;
|
||||||
private allowedOrigin: string;
|
/**
|
||||||
|
* The origin of the iframe content that messages will be sent to.
|
||||||
|
* Used as the 'targetOrigin' parameter in postMessage calls.
|
||||||
|
* Initially set to '*' (insecure) until the actual iframe URL is loaded.
|
||||||
|
*
|
||||||
|
* SECURITY NOTE: The value '*' should be replaced with the actual origin
|
||||||
|
* as soon as possible using setTargetOrigin().
|
||||||
|
*/
|
||||||
|
private targetIframeOrigin: string;
|
||||||
/**
|
/**
|
||||||
* A map to store event handlers for different events.
|
* A map to store event handlers for different events.
|
||||||
* This allows for dynamic event handling and can be used to add or remove event listeners.
|
* This allows for dynamic event handling and can be used to add or remove event listeners.
|
||||||
@ -21,9 +29,15 @@ export class CommandsManager {
|
|||||||
*/
|
*/
|
||||||
private eventHandlers: Map<string, Set<Function>> = new Map();
|
private eventHandlers: Map<string, Set<Function>> = new Map();
|
||||||
|
|
||||||
constructor(iframe: HTMLIFrameElement, allowedOrigin: string) {
|
/**
|
||||||
|
* Creates a new CommandsManager instance
|
||||||
|
*
|
||||||
|
* @param iframe - The iframe element used for communication
|
||||||
|
* @param initialTargetOrigin - The initial target origin for postMessage
|
||||||
|
*/
|
||||||
|
constructor(iframe: HTMLIFrameElement, initialTargetOrigin: string) {
|
||||||
this.iframe = iframe;
|
this.iframe = iframe;
|
||||||
this.allowedOrigin = allowedOrigin;
|
this.targetIframeOrigin = initialTargetOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,16 +162,24 @@ export class CommandsManager {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the allowed origin for the current instance.
|
* Updates the target origin used when sending messages to the iframe.
|
||||||
|
* This should be called once the iframe URL is known to improve security.
|
||||||
*
|
*
|
||||||
* @param newOrigin - The new origin to be set as allowed.
|
* @param newOrigin - The origin of the content loaded in the iframe
|
||||||
|
* (e.g. 'https://meet.example.com')
|
||||||
*/
|
*/
|
||||||
public setAllowedOrigin(newOrigin: string): void {
|
public setTargetOrigin(newOrigin: string): void {
|
||||||
this.allowedOrigin = newOrigin;
|
this.targetIframeOrigin = newOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendMessage(message: InboundCommandMessage, targetOrigin?: string): void {
|
/**
|
||||||
targetOrigin = targetOrigin || this.allowedOrigin;
|
* Sends a message to the iframe using window.postMessage
|
||||||
this.iframe.contentWindow?.postMessage(message, targetOrigin);
|
*
|
||||||
|
* @param message - The message to send to the iframe
|
||||||
|
* @param explicitTargetOrigin - Optional override for the target origin
|
||||||
|
*/
|
||||||
|
private sendMessage(message: InboundCommandMessage, explicitTargetOrigin?: string): void {
|
||||||
|
explicitTargetOrigin = explicitTargetOrigin || this.targetIframeOrigin;
|
||||||
|
this.iframe.contentWindow?.postMessage(message, explicitTargetOrigin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { WebComponentCommand } from '../models/command.model';
|
|
||||||
import { InboundCommandMessage } from '../models/message.type';
|
|
||||||
import { CommandsManager } from './CommandsManager';
|
import { CommandsManager } from './CommandsManager';
|
||||||
import { EventsManager } from './EventsManager';
|
import { EventsManager } from './EventsManager';
|
||||||
import styles from '../assets/css/styles.css';
|
import styles from '../assets/css/styles.css';
|
||||||
@ -30,7 +28,7 @@ export class OpenViduMeet extends HTMLElement {
|
|||||||
private commandsManager: CommandsManager;
|
private commandsManager: CommandsManager;
|
||||||
private eventsManager: EventsManager;
|
private eventsManager: EventsManager;
|
||||||
//!FIXME: Insecure by default
|
//!FIXME: Insecure by default
|
||||||
private allowedOrigin: string = '*';
|
private targetIframeOrigin: string = '*';
|
||||||
private loadTimeout: any;
|
private loadTimeout: any;
|
||||||
private iframeLoaded = false;
|
private iframeLoaded = false;
|
||||||
private errorMessage: string | null = null;
|
private errorMessage: string | null = null;
|
||||||
@ -44,7 +42,7 @@ export class OpenViduMeet extends HTMLElement {
|
|||||||
'camera; microphone; display-capture; fullscreen; autoplay; compute-pressure;'
|
'camera; microphone; display-capture; fullscreen; autoplay; compute-pressure;'
|
||||||
);
|
);
|
||||||
|
|
||||||
this.commandsManager = new CommandsManager(this.iframe, this.allowedOrigin);
|
this.commandsManager = new CommandsManager(this.iframe, this.targetIframeOrigin);
|
||||||
this.eventsManager = new EventsManager(this);
|
this.eventsManager = new EventsManager(this);
|
||||||
|
|
||||||
// Listen for changes in attributes to update the iframe src
|
// Listen for changes in attributes to update the iframe src
|
||||||
@ -140,8 +138,8 @@ export class OpenViduMeet extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(baseUrl);
|
const url = new URL(baseUrl);
|
||||||
this.allowedOrigin = url.origin;
|
this.targetIframeOrigin = url.origin;
|
||||||
this.commandsManager.setAllowedOrigin(this.allowedOrigin);
|
this.commandsManager.setTargetOrigin(this.targetIframeOrigin);
|
||||||
|
|
||||||
// Update query params
|
// Update query params
|
||||||
Array.from(this.attributes).forEach((attr) => {
|
Array.from(this.attributes).forEach((attr) => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user