globalpayments / globalpayments-js

JavaScript library for web applications to connect to Heartland eCommerce & Global Payments eCommerce tokenization services
14 stars 23 forks source link

EventListener in postToIframe consumes events from 3rd party libraries #74

Open ArtemDynatrace opened 1 year ago

ArtemDynatrace commented 1 year ago

Hi,

Our customer uses globalpayments-3ds library and also Dynatrace Session Replay agent (the library that records user sessions) on the same webpage.

Session Replay agent uses postMessage for communication between a web worker and the main page, the same channel that globalpayments-3ds library uses when doing the challenge (as a part of the payment flow), which leads to a conflict.

Inside globalpayments-3ds, postToIframe sets up the listener, provided by getWindowMessageEventHandler (packages\globalpayments-3ds\src\lib\post-to-iframe.ts):

function getWindowMessageEventHandler(
  resolve: (data: IMessageEventData | PromiseLike<IMessageEventData>) => void,
  data: IIframeData,
) {
  return (e: MessageEvent) => {
    const origin = data.origin || window.location.origin;

    if (origin !== e.origin) {
      return;
    }

    ensureIframeClosed(data.timeout || 0);
    resolve(e.data);
  };
}

The event handler is supposed to receive the message with event: 'challengeNotification', but it first sees the message that was sent by the Dynatrace Session Replay agent, and tries to process it.

For both messages, data.origin is undefined and e.origin is the customer's domain, so you cannot tell them apart based on the origin alone. getWindowMessageEventHandler does not perform any further checks and simply resolves the promise with the event that originates from the Dynatrace Session Replay agent, breaking the 3ds integration.

This is not unique to the Dynatrace Session Replay recorder and globalpayments-3ds interaction. This also happens when you enable Angular Dev Tools, basically any 3rd party library that would use postMessage could potentially "trick" the globalpayments-3ds into consuming its event.

Dynatrace Session Replay agent never consumes the events from globalpayments-3ds, as we check for the message type (the custom property in the payload of the message).

Could globalpayments-3ds implement the extra check in the getWindowMessageEventHandler to make sure it only consumes the relevant events and ignores all the rest? Thank you!

ahumulescu commented 1 year ago

Hello,

Sorry for the delay.

This issue was addressed in the latest version of the globalpayments-3ds library (1.8.6) and it should be fixed now.

ArtemDynatrace commented 1 year ago

Hi, thank you!