@everymatrix/player-step-up-auth 0.1.2 → 1.64.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const playerStepUpAuth = require('./player-step-up-auth-71fe684b.js');
5
+ const playerStepUpAuth = require('./player-step-up-auth-f18f2787.js');
6
6
  require('./index-bf4d774c.js');
7
7
 
8
8
 
@@ -8,7 +8,7 @@ const appGlobals = require('./app-globals-3a1e7e63.js');
8
8
  const defineCustomElements = async (win, options) => {
9
9
  if (typeof window === 'undefined') return undefined;
10
10
  await appGlobals.globalScripts();
11
- return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
11
+ return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
12
12
  };
13
13
 
14
14
  exports.setNonce = index.setNonce;
@@ -270,6 +270,19 @@ const PlayerStepUpAuth = class {
270
270
  setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
271
271
  }
272
272
  }
273
+ /**
274
+ * Handles the custom `stepUpAuthRequired` event fired on the window.
275
+ * This event typically signals that step-up authentication is required.
276
+ *
277
+ * @param event - A CustomEvent that contains authentication-related details.
278
+ *
279
+ * Expected `event.detail` structure:
280
+ * {
281
+ * 'x-step-up-required': true,
282
+ * 'x-step-up-token': string,
283
+ * 'flow': string
284
+ * }
285
+ */
273
286
  async handleStepUpAuthEvent(event) {
274
287
  var _a;
275
288
  if ((_a = event.detail) === null || _a === void 0 ? void 0 : _a['x-step-up-required']) {
@@ -278,9 +291,24 @@ const PlayerStepUpAuth = class {
278
291
  this.errorMessage = '';
279
292
  this.showPopup = true;
280
293
  this.token = event.detail['x-step-up-token'];
294
+ this.flow = event.detail['flow'];
295
+ if (!this.token || !this.flow) {
296
+ this.isLoading = false;
297
+ this.hasConfigErrors = true;
298
+ this.errorMessage = translate('configError', this.language);
299
+ return;
300
+ }
281
301
  await this.getConfig();
282
302
  }
283
303
  }
304
+ /**
305
+ * Listens for the 'closePopup' event dispatched on the window
306
+ * and triggers popup closing logic. This allows other components
307
+ * or scripts to close the popup via a custom event.
308
+ */
309
+ handleCloseWidget() {
310
+ this.closePopup();
311
+ }
284
312
  /**
285
313
  * Class constructor
286
314
  */
@@ -306,6 +334,7 @@ const PlayerStepUpAuth = class {
306
334
  this.hasConfigErrors = false;
307
335
  this.errorMessage = '';
308
336
  this.token = '';
337
+ this.flow = '';
309
338
  this.showResendOtp = false;
310
339
  this.closePopup = this.closePopup.bind(this);
311
340
  this.handleResendOtp = this.handleResendOtp.bind(this);
@@ -331,6 +360,14 @@ const PlayerStepUpAuth = class {
331
360
  this.showResendOtp = false;
332
361
  this.expirationTime = this.config.expirationTime;
333
362
  this.serverTime = this.config.serverTime;
363
+ /**
364
+ * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
365
+ * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
366
+ */
367
+ if (this.config.numberOfValidateAttempts !== 0) {
368
+ this.hasErrors = true;
369
+ this.errorMessage = translate('invalidOtp', this.language);
370
+ }
334
371
  this.calculateTimeLeft();
335
372
  this.startCountdown();
336
373
  }
@@ -475,9 +512,7 @@ const PlayerStepUpAuth = class {
475
512
  */
476
513
  handleResendOtp() {
477
514
  // Emit an event to notify the system that OTP should be resent
478
- const event = new CustomEvent('otpResendRequested', {
479
- detail: { message: 'User requested OTP resend' }
480
- });
515
+ const event = new CustomEvent('otpResendRequested');
481
516
  window.dispatchEvent(event);
482
517
  }
483
518
  /**
@@ -494,6 +529,30 @@ const PlayerStepUpAuth = class {
494
529
  this.hasErrors = false;
495
530
  this.errorMessage = '';
496
531
  const otpValue = this.otp.join('');
532
+ if (this.flow === 'stateless') {
533
+ this.handleOtpStateless(otpValue);
534
+ }
535
+ if (this.flow === 'stateful') {
536
+ await this.handleOtpStateful(otpValue);
537
+ }
538
+ }
539
+ /**
540
+ * Handle stateless mode where we just need to send the otp value and the template will
541
+ * recall the endpoint with X-Step-Up-Token and X-Step-Up-Value (otp value)
542
+ *
543
+ * @param otpValue - Otp code.
544
+ */
545
+ handleOtpStateless(otpValue) {
546
+ window.dispatchEvent(new CustomEvent('otpSubmitted', {
547
+ detail: { code: otpValue }
548
+ }));
549
+ }
550
+ /**
551
+ * Handle the stateful mode where we need to call validate endpoint.
552
+ *
553
+ * @param otpValue - Otp code.
554
+ */
555
+ async handleOtpStateful(otpValue) {
497
556
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/validate`, this.endpoint);
498
557
  url.searchParams.append('input', otpValue);
499
558
  try {
@@ -556,10 +615,10 @@ const PlayerStepUpAuth = class {
556
615
  * Resets the authentication UI state.
557
616
  */
558
617
  closePopup() {
618
+ this.hasErrors = false;
619
+ this.hasConfigErrors = false;
620
+ this.errorMessage = '';
559
621
  this.showPopup = false;
560
- window.dispatchEvent(new CustomEvent('popupClosed', {
561
- detail: { message: 'User closed the popup' }
562
- }));
563
622
  }
564
623
  /**
565
624
  * Lifecycle method: Clean up event listeners when the component is removed
@@ -600,7 +659,7 @@ const PlayerStepUpAuth = class {
600
659
  * Displays the OTP popup, input fields, timer, and action buttons.
601
660
  */
602
661
  render() {
603
- return (index.h("div", { key: '1e969334bcc5ef26826a600bd3743037765ceeb0', ref: el => this.stylingContainer = el }, this.showPopup && (index.h("div", { key: 'f85bc272fed6e9ccc54fd21d7f79d81a3f3b9983', class: "OtpPopupOverlay" }, index.h("div", { key: '8ef3f980d3f03034b7f16f97f1f7c4a15f400189', class: "OtpPopupContent" }, this.isLoading ? (index.h("div", { class: "OtpLoaderContainer" }, index.h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (index.h("div", { class: "OtpError" }, index.h("div", { class: "OtpErrorHeader" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, index.h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), index.h("h2", null, translate('errorHeader', this.language))), index.h("p", null, this.errorMessage), index.h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (index.h(index.Fragment, null, index.h("div", { class: "otp-description" }, index.h("p", null, translate('popupMessage', this.language)), this.hasErrors && index.h("p", { class: "OtpErrorMessage" }, this.errorMessage)), index.h("div", { class: "OtpFieldWrapper" }, index.h("h2", null, translate('otpHeading', this.language)), index.h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index$1) => {
662
+ return (index.h("div", { key: '737e607eec48c578b6714930c7b4a4df33949b67', ref: el => this.stylingContainer = el }, this.showPopup && (index.h("div", { key: '0edf00aceccbf267a7c026510e751787e423975b', class: "OtpPopupOverlay" }, index.h("div", { key: '6a410ac15a1db1eebff9e406a6ebb89bba398764', class: "OtpPopupContent" }, this.isLoading ? (index.h("div", { class: "OtpLoaderContainer" }, index.h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (index.h("div", { class: "OtpError" }, index.h("div", { class: "OtpErrorHeader" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, index.h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), index.h("h2", null, translate('errorHeader', this.language))), index.h("p", null, this.errorMessage), index.h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (index.h(index.Fragment, null, index.h("div", { class: "otp-description" }, index.h("p", null, translate('popupMessage', this.language)), this.hasErrors && index.h("p", { class: "OtpErrorMessage" }, this.errorMessage)), index.h("div", { class: "OtpFieldWrapper" }, index.h("h2", null, translate('otpHeading', this.language)), index.h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index$1) => {
604
663
  const isHalfway = this.config.inputLength % 2 === 0 && index$1 === (this.config.inputLength / 2) - 1;
605
664
  return (index.h("input", { key: index$1, ref: el => this.setOtpInputRef(el, index$1), id: `otp-input-${index$1}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index$1), onKeyDown: (event) => this.handleKeyDown(event, index$1), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
606
665
  })), index.h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), index.h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (index.h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (index.h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), index.h("button", { class: "OtpButton", onClick: this.closePopup }, translate('close', this.language)))))))))));
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const playerStepUpAuth = require('./player-step-up-auth-71fe684b.js');
5
+ const playerStepUpAuth = require('./player-step-up-auth-f18f2787.js');
6
6
  require('./index-bf4d774c.js');
7
7
 
8
8
 
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
22
+ return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -31,6 +31,19 @@ export class PlayerStepUpAuth {
31
31
  setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
32
32
  }
33
33
  }
34
+ /**
35
+ * Handles the custom `stepUpAuthRequired` event fired on the window.
36
+ * This event typically signals that step-up authentication is required.
37
+ *
38
+ * @param event - A CustomEvent that contains authentication-related details.
39
+ *
40
+ * Expected `event.detail` structure:
41
+ * {
42
+ * 'x-step-up-required': true,
43
+ * 'x-step-up-token': string,
44
+ * 'flow': string
45
+ * }
46
+ */
34
47
  async handleStepUpAuthEvent(event) {
35
48
  var _a;
36
49
  if ((_a = event.detail) === null || _a === void 0 ? void 0 : _a['x-step-up-required']) {
@@ -39,9 +52,24 @@ export class PlayerStepUpAuth {
39
52
  this.errorMessage = '';
40
53
  this.showPopup = true;
41
54
  this.token = event.detail['x-step-up-token'];
55
+ this.flow = event.detail['flow'];
56
+ if (!this.token || !this.flow) {
57
+ this.isLoading = false;
58
+ this.hasConfigErrors = true;
59
+ this.errorMessage = translate('configError', this.language);
60
+ return;
61
+ }
42
62
  await this.getConfig();
43
63
  }
44
64
  }
65
+ /**
66
+ * Listens for the 'closePopup' event dispatched on the window
67
+ * and triggers popup closing logic. This allows other components
68
+ * or scripts to close the popup via a custom event.
69
+ */
70
+ handleCloseWidget() {
71
+ this.closePopup();
72
+ }
45
73
  /**
46
74
  * Class constructor
47
75
  */
@@ -66,6 +94,7 @@ export class PlayerStepUpAuth {
66
94
  this.hasConfigErrors = false;
67
95
  this.errorMessage = '';
68
96
  this.token = '';
97
+ this.flow = '';
69
98
  this.showResendOtp = false;
70
99
  this.closePopup = this.closePopup.bind(this);
71
100
  this.handleResendOtp = this.handleResendOtp.bind(this);
@@ -91,6 +120,14 @@ export class PlayerStepUpAuth {
91
120
  this.showResendOtp = false;
92
121
  this.expirationTime = this.config.expirationTime;
93
122
  this.serverTime = this.config.serverTime;
123
+ /**
124
+ * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
125
+ * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
126
+ */
127
+ if (this.config.numberOfValidateAttempts !== 0) {
128
+ this.hasErrors = true;
129
+ this.errorMessage = translate('invalidOtp', this.language);
130
+ }
94
131
  this.calculateTimeLeft();
95
132
  this.startCountdown();
96
133
  }
@@ -235,9 +272,7 @@ export class PlayerStepUpAuth {
235
272
  */
236
273
  handleResendOtp() {
237
274
  // Emit an event to notify the system that OTP should be resent
238
- const event = new CustomEvent('otpResendRequested', {
239
- detail: { message: 'User requested OTP resend' }
240
- });
275
+ const event = new CustomEvent('otpResendRequested');
241
276
  window.dispatchEvent(event);
242
277
  }
243
278
  /**
@@ -254,6 +289,30 @@ export class PlayerStepUpAuth {
254
289
  this.hasErrors = false;
255
290
  this.errorMessage = '';
256
291
  const otpValue = this.otp.join('');
292
+ if (this.flow === 'stateless') {
293
+ this.handleOtpStateless(otpValue);
294
+ }
295
+ if (this.flow === 'stateful') {
296
+ await this.handleOtpStateful(otpValue);
297
+ }
298
+ }
299
+ /**
300
+ * Handle stateless mode where we just need to send the otp value and the template will
301
+ * recall the endpoint with X-Step-Up-Token and X-Step-Up-Value (otp value)
302
+ *
303
+ * @param otpValue - Otp code.
304
+ */
305
+ handleOtpStateless(otpValue) {
306
+ window.dispatchEvent(new CustomEvent('otpSubmitted', {
307
+ detail: { code: otpValue }
308
+ }));
309
+ }
310
+ /**
311
+ * Handle the stateful mode where we need to call validate endpoint.
312
+ *
313
+ * @param otpValue - Otp code.
314
+ */
315
+ async handleOtpStateful(otpValue) {
257
316
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/validate`, this.endpoint);
258
317
  url.searchParams.append('input', otpValue);
259
318
  try {
@@ -316,10 +375,10 @@ export class PlayerStepUpAuth {
316
375
  * Resets the authentication UI state.
317
376
  */
318
377
  closePopup() {
378
+ this.hasErrors = false;
379
+ this.hasConfigErrors = false;
380
+ this.errorMessage = '';
319
381
  this.showPopup = false;
320
- window.dispatchEvent(new CustomEvent('popupClosed', {
321
- detail: { message: 'User closed the popup' }
322
- }));
323
382
  }
324
383
  /**
325
384
  * Lifecycle method: Clean up event listeners when the component is removed
@@ -360,7 +419,7 @@ export class PlayerStepUpAuth {
360
419
  * Displays the OTP popup, input fields, timer, and action buttons.
361
420
  */
362
421
  render() {
363
- return (h("div", { key: '1e969334bcc5ef26826a600bd3743037765ceeb0', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'f85bc272fed6e9ccc54fd21d7f79d81a3f3b9983', class: "OtpPopupOverlay" }, h("div", { key: '8ef3f980d3f03034b7f16f97f1f7c4a15f400189', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, h("p", null, translate('popupMessage', this.language)), this.hasErrors && h("p", { class: "OtpErrorMessage" }, this.errorMessage)), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
422
+ return (h("div", { key: '737e607eec48c578b6714930c7b4a4df33949b67', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: '0edf00aceccbf267a7c026510e751787e423975b', class: "OtpPopupOverlay" }, h("div", { key: '6a410ac15a1db1eebff9e406a6ebb89bba398764', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, h("p", null, translate('popupMessage', this.language)), this.hasErrors && h("p", { class: "OtpErrorMessage" }, this.errorMessage)), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
364
423
  const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
365
424
  return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
366
425
  })), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.closePopup }, translate('close', this.language)))))))))));
@@ -515,6 +574,7 @@ export class PlayerStepUpAuth {
515
574
  "hasConfigErrors": {},
516
575
  "errorMessage": {},
517
576
  "token": {},
577
+ "flow": {},
518
578
  "showResendOtp": {}
519
579
  };
520
580
  }
@@ -538,6 +598,12 @@ export class PlayerStepUpAuth {
538
598
  "target": "window",
539
599
  "capture": false,
540
600
  "passive": false
601
+ }, {
602
+ "name": "closePopup",
603
+ "method": "handleCloseWidget",
604
+ "target": "window",
605
+ "capture": false,
606
+ "passive": false
541
607
  }];
542
608
  }
543
609
  }
package/dist/esm/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { P as PlayerStepUpAuth } from './player-step-up-auth-a1207cba.js';
1
+ export { P as PlayerStepUpAuth } from './player-step-up-auth-62cf8fb9.js';
2
2
  import './index-c6eee6d8.js';
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-0f993ce5.js';
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await globalScripts();
8
- return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
8
+ return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
9
9
  };
10
10
 
11
11
  export { defineCustomElements };
@@ -268,6 +268,19 @@ const PlayerStepUpAuth = class {
268
268
  setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
269
269
  }
270
270
  }
271
+ /**
272
+ * Handles the custom `stepUpAuthRequired` event fired on the window.
273
+ * This event typically signals that step-up authentication is required.
274
+ *
275
+ * @param event - A CustomEvent that contains authentication-related details.
276
+ *
277
+ * Expected `event.detail` structure:
278
+ * {
279
+ * 'x-step-up-required': true,
280
+ * 'x-step-up-token': string,
281
+ * 'flow': string
282
+ * }
283
+ */
271
284
  async handleStepUpAuthEvent(event) {
272
285
  var _a;
273
286
  if ((_a = event.detail) === null || _a === void 0 ? void 0 : _a['x-step-up-required']) {
@@ -276,9 +289,24 @@ const PlayerStepUpAuth = class {
276
289
  this.errorMessage = '';
277
290
  this.showPopup = true;
278
291
  this.token = event.detail['x-step-up-token'];
292
+ this.flow = event.detail['flow'];
293
+ if (!this.token || !this.flow) {
294
+ this.isLoading = false;
295
+ this.hasConfigErrors = true;
296
+ this.errorMessage = translate('configError', this.language);
297
+ return;
298
+ }
279
299
  await this.getConfig();
280
300
  }
281
301
  }
302
+ /**
303
+ * Listens for the 'closePopup' event dispatched on the window
304
+ * and triggers popup closing logic. This allows other components
305
+ * or scripts to close the popup via a custom event.
306
+ */
307
+ handleCloseWidget() {
308
+ this.closePopup();
309
+ }
282
310
  /**
283
311
  * Class constructor
284
312
  */
@@ -304,6 +332,7 @@ const PlayerStepUpAuth = class {
304
332
  this.hasConfigErrors = false;
305
333
  this.errorMessage = '';
306
334
  this.token = '';
335
+ this.flow = '';
307
336
  this.showResendOtp = false;
308
337
  this.closePopup = this.closePopup.bind(this);
309
338
  this.handleResendOtp = this.handleResendOtp.bind(this);
@@ -329,6 +358,14 @@ const PlayerStepUpAuth = class {
329
358
  this.showResendOtp = false;
330
359
  this.expirationTime = this.config.expirationTime;
331
360
  this.serverTime = this.config.serverTime;
361
+ /**
362
+ * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
363
+ * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
364
+ */
365
+ if (this.config.numberOfValidateAttempts !== 0) {
366
+ this.hasErrors = true;
367
+ this.errorMessage = translate('invalidOtp', this.language);
368
+ }
332
369
  this.calculateTimeLeft();
333
370
  this.startCountdown();
334
371
  }
@@ -473,9 +510,7 @@ const PlayerStepUpAuth = class {
473
510
  */
474
511
  handleResendOtp() {
475
512
  // Emit an event to notify the system that OTP should be resent
476
- const event = new CustomEvent('otpResendRequested', {
477
- detail: { message: 'User requested OTP resend' }
478
- });
513
+ const event = new CustomEvent('otpResendRequested');
479
514
  window.dispatchEvent(event);
480
515
  }
481
516
  /**
@@ -492,6 +527,30 @@ const PlayerStepUpAuth = class {
492
527
  this.hasErrors = false;
493
528
  this.errorMessage = '';
494
529
  const otpValue = this.otp.join('');
530
+ if (this.flow === 'stateless') {
531
+ this.handleOtpStateless(otpValue);
532
+ }
533
+ if (this.flow === 'stateful') {
534
+ await this.handleOtpStateful(otpValue);
535
+ }
536
+ }
537
+ /**
538
+ * Handle stateless mode where we just need to send the otp value and the template will
539
+ * recall the endpoint with X-Step-Up-Token and X-Step-Up-Value (otp value)
540
+ *
541
+ * @param otpValue - Otp code.
542
+ */
543
+ handleOtpStateless(otpValue) {
544
+ window.dispatchEvent(new CustomEvent('otpSubmitted', {
545
+ detail: { code: otpValue }
546
+ }));
547
+ }
548
+ /**
549
+ * Handle the stateful mode where we need to call validate endpoint.
550
+ *
551
+ * @param otpValue - Otp code.
552
+ */
553
+ async handleOtpStateful(otpValue) {
495
554
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/validate`, this.endpoint);
496
555
  url.searchParams.append('input', otpValue);
497
556
  try {
@@ -554,10 +613,10 @@ const PlayerStepUpAuth = class {
554
613
  * Resets the authentication UI state.
555
614
  */
556
615
  closePopup() {
616
+ this.hasErrors = false;
617
+ this.hasConfigErrors = false;
618
+ this.errorMessage = '';
557
619
  this.showPopup = false;
558
- window.dispatchEvent(new CustomEvent('popupClosed', {
559
- detail: { message: 'User closed the popup' }
560
- }));
561
620
  }
562
621
  /**
563
622
  * Lifecycle method: Clean up event listeners when the component is removed
@@ -598,7 +657,7 @@ const PlayerStepUpAuth = class {
598
657
  * Displays the OTP popup, input fields, timer, and action buttons.
599
658
  */
600
659
  render() {
601
- return (h("div", { key: '1e969334bcc5ef26826a600bd3743037765ceeb0', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'f85bc272fed6e9ccc54fd21d7f79d81a3f3b9983', class: "OtpPopupOverlay" }, h("div", { key: '8ef3f980d3f03034b7f16f97f1f7c4a15f400189', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, h("p", null, translate('popupMessage', this.language)), this.hasErrors && h("p", { class: "OtpErrorMessage" }, this.errorMessage)), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
660
+ return (h("div", { key: '737e607eec48c578b6714930c7b4a4df33949b67', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: '0edf00aceccbf267a7c026510e751787e423975b', class: "OtpPopupOverlay" }, h("div", { key: '6a410ac15a1db1eebff9e406a6ebb89bba398764', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.closePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, h("p", null, translate('popupMessage', this.language)), this.hasErrors && h("p", { class: "OtpErrorMessage" }, this.errorMessage)), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
602
661
  const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
603
662
  return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
604
663
  })), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.closePopup }, translate('close', this.language)))))))))));
@@ -1,2 +1,2 @@
1
- export { P as player_step_up_auth } from './player-step-up-auth-a1207cba.js';
1
+ export { P as player_step_up_auth } from './player-step-up-auth-62cf8fb9.js';
2
2
  import './index-c6eee6d8.js';
@@ -16,5 +16,5 @@ var patchBrowser = () => {
16
16
 
17
17
  patchBrowser().then(async (options) => {
18
18
  await globalScripts();
19
- return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
19
+ return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
20
20
  });
@@ -1 +1 @@
1
- export{P as PlayerStepUpAuth}from"./p-00b18944.js";import"./p-c6a4faff.js";
1
+ export{P as PlayerStepUpAuth}from"./p-f8171a4e.js";import"./p-c6a4faff.js";
@@ -0,0 +1 @@
1
+ export{P as player_step_up_auth}from"./p-f8171a4e.js";import"./p-c6a4faff.js";
@@ -0,0 +1 @@
1
+ import{r as e,h as t,F as i,g as r}from"./p-c6a4faff.js";function o(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function s(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const n={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente."}},a=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])n[t][i]=e[t][i]})),t(!0)}))})),l=(e,t)=>n[void 0!==t?t:"en"][e],d=class{handleNewTranslations(){a(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&o(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&s(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;if(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"]){if(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],this.flow=e.detail.flow,!this.token||!this.flow)return this.isLoading=!1,this.hasConfigErrors=!0,void(this.errorMessage=l("configError",this.language));await this.getConfig()}}handleCloseWidget(){this.closePopup()}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.flow="",this.showResendOtp=!1,this.closePopup=this.closePopup.bind(this),this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.setOtpContainerRef=this.setOtpContainerRef.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href);if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);this.config=await t.json(),this.otp=new Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,0!==this.config.numberOfValidateAttempts&&(this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language)),this.calculateTimeLeft(),this.startCountdown()}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=l("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime);this.currentTime||(this.currentTime=new Date);const i=t.getTime()-this.currentTime.getTime(),r=new Date(this.currentTime.getTime()+i);this.timeLeft=Math.floor((e.getTime()-r.getTime())/1e3)}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{this.timeLeft>0?this.timeLeft-=1:(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpContainerRef(e){e&&(this.otpContainer=e)}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}handleOnPasteOtp(e){var t;e.preventDefault();const i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text").trim();if(!i)return;const r=i.slice(0,this.config.inputLength).split("");this.otp=[...r,...new Array(this.config.inputLength-r.length).fill("")];const o=Array.from(this.otpContainer.children);if(o){r.forEach(((e,t)=>{o[t].value=e}));const e=o[r.length-1];null==e||e.focus(),r.length===this.config.inputLength&&this.submitOtp()}}handleOtpInput(e,t){const i=e.target;let r=i.value.replace(/[^0-9a-zA-Z]/gi,"").toUpperCase();if(i.value=r.charAt(0),!r)return;this.otp[t]=r[0];const o=this.otpInputs[t+1];null==o||o.focus()}handleKeyDown(e,t){if("Backspace"===e.key){this.otp[t]="",this.otpInputs[t].value="";const e=this.otpInputs[t-1];null==e||e.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested");window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=l("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join("");"stateless"===this.flow&&this.handleOtpStateless(e),"stateful"===this.flow&&await this.handleOtpStateful(e)}handleOtpStateless(e){window.dispatchEvent(new CustomEvent("otpSubmitted",{detail:{code:e}}))}async handleOtpStateful(e){const t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.challenge"===e.message){if(this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1){const e=new Date(this.serverTime);e.setHours(e.getHours()+1);const t=e.toISOString().slice(0,16).replace("T"," ");return window.postMessage({type:"SetPlayerAccountTimeout",timeoutSelected:"CoolOffUntilSelectedDate",timeoutExpiryDate:t},window.location.href),window.postMessage({type:"WidgetNotification",data:{type:"error",message:l("accountBlocked",this.language)}},window.location.href),void this.closePopup()}return this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language),void this.getConfig()}console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=l("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.closePopup()}closePopup(){this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.showPopup=!1}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await a(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&o(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&s(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"737e607eec48c578b6714930c7b4a4df33949b67",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"0edf00aceccbf267a7c026510e751787e423975b",class:"OtpPopupOverlay"},t("div",{key:"6a410ac15a1db1eebff9e406a6ebb89bba398764",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,l("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.closePopup},l("close",this.language))):t(i,null,t("div",{class:"otp-description"},t("p",null,l("popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage"},this.errorMessage)),t("div",{class:"OtpFieldWrapper"},t("h2",null,l("otpHeading",this.language)),t("div",{class:"OtpField",ref:this.setOtpContainerRef},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.timeLeft<=0})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",l("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},l("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},l("submit",this.language)),t("button",{class:"OtpButton",onClick:this.closePopup},l("close",this.language)))))))}get el(){return r(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};d.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{d as P}
@@ -1 +1 @@
1
- import{p as e,b as n}from"./p-c6a4faff.js";export{s as setNonce}from"./p-c6a4faff.js";import{g as t}from"./p-e1255160.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["p-2a1bcef9",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],showResendOtp:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
1
+ import{p as e,b as n}from"./p-c6a4faff.js";export{s as setNonce}from"./p-c6a4faff.js";import{g as t}from"./p-e1255160.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["p-849e390a",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],flow:[32],showResendOtp:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
@@ -39,6 +39,7 @@ export declare class PlayerStepUpAuth {
39
39
  hasConfigErrors: boolean;
40
40
  errorMessage: string;
41
41
  token: string;
42
+ flow: string;
42
43
  showResendOtp: boolean;
43
44
  private stylingContainer;
44
45
  private stylingSubscription;
@@ -64,7 +65,26 @@ export declare class PlayerStepUpAuth {
64
65
  * @param oldValue - previous client styling URL
65
66
  */
66
67
  handleClientStylingUrlChange(newValue: string, oldValue: string): void;
68
+ /**
69
+ * Handles the custom `stepUpAuthRequired` event fired on the window.
70
+ * This event typically signals that step-up authentication is required.
71
+ *
72
+ * @param event - A CustomEvent that contains authentication-related details.
73
+ *
74
+ * Expected `event.detail` structure:
75
+ * {
76
+ * 'x-step-up-required': true,
77
+ * 'x-step-up-token': string,
78
+ * 'flow': string
79
+ * }
80
+ */
67
81
  handleStepUpAuthEvent(event: CustomEvent): Promise<void>;
82
+ /**
83
+ * Listens for the 'closePopup' event dispatched on the window
84
+ * and triggers popup closing logic. This allows other components
85
+ * or scripts to close the popup via a custom event.
86
+ */
87
+ handleCloseWidget(): void;
68
88
  /**
69
89
  * Class constructor
70
90
  */
@@ -138,6 +158,19 @@ export declare class PlayerStepUpAuth {
138
158
  * Sends a request to the endpoint with the OTP and handles the response.
139
159
  */
140
160
  submitOtp(): Promise<void>;
161
+ /**
162
+ * Handle stateless mode where we just need to send the otp value and the template will
163
+ * recall the endpoint with X-Step-Up-Token and X-Step-Up-Value (otp value)
164
+ *
165
+ * @param otpValue - Otp code.
166
+ */
167
+ handleOtpStateless(otpValue: string): void;
168
+ /**
169
+ * Handle the stateful mode where we need to call validate endpoint.
170
+ *
171
+ * @param otpValue - Otp code.
172
+ */
173
+ handleOtpStateful(otpValue: string): Promise<void>;
141
174
  /**
142
175
  * Handles successful OTP validation.
143
176
  * Closes the popup upon successful authentication.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everymatrix/player-step-up-auth",
3
- "version": "0.1.2",
3
+ "version": "1.64.2",
4
4
  "main": "./dist/index.cjs.js",
5
5
  "module": "./dist/index.js",
6
6
  "es2015": "./dist/esm/index.mjs",
@@ -21,7 +21,6 @@
21
21
  "loader/"
22
22
  ],
23
23
  "publishConfig": {
24
- "access": "public",
25
- "registry": "https://everymatrix.jfrog.io/artifactory/api/npm/everymatrix-widgets/"
24
+ "access": "public"
26
25
  }
27
26
  }
@@ -1 +0,0 @@
1
- import{r as e,h as t,F as i,g as r}from"./p-c6a4faff.js";function o(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function s(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const n={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente."}},a=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])n[t][i]=e[t][i]})),t(!0)}))})),d=(e,t)=>n[void 0!==t?t:"en"][e],l=class{handleNewTranslations(){a(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&o(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&s(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"])&&(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],await this.getConfig())}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.showResendOtp=!1,this.closePopup=this.closePopup.bind(this),this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.setOtpContainerRef=this.setOtpContainerRef.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href);if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);this.config=await t.json(),this.otp=new Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,this.calculateTimeLeft(),this.startCountdown()}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=d("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime);this.currentTime||(this.currentTime=new Date);const i=t.getTime()-this.currentTime.getTime(),r=new Date(this.currentTime.getTime()+i);this.timeLeft=Math.floor((e.getTime()-r.getTime())/1e3)}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{this.timeLeft>0?this.timeLeft-=1:(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpContainerRef(e){e&&(this.otpContainer=e)}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}handleOnPasteOtp(e){var t;e.preventDefault();const i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text").trim();if(!i)return;const r=i.slice(0,this.config.inputLength).split("");this.otp=[...r,...new Array(this.config.inputLength-r.length).fill("")];const o=Array.from(this.otpContainer.children);if(o){r.forEach(((e,t)=>{o[t].value=e}));const e=o[r.length-1];null==e||e.focus(),r.length===this.config.inputLength&&this.submitOtp()}}handleOtpInput(e,t){const i=e.target;let r=i.value.replace(/[^0-9a-zA-Z]/gi,"").toUpperCase();if(i.value=r.charAt(0),!r)return;this.otp[t]=r[0];const o=this.otpInputs[t+1];null==o||o.focus()}handleKeyDown(e,t){if("Backspace"===e.key){this.otp[t]="",this.otpInputs[t].value="";const e=this.otpInputs[t-1];null==e||e.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested",{detail:{message:"User requested OTP resend"}});window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=d("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join(""),t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.challenge"===e.message){if(this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1){const e=new Date(this.serverTime);e.setHours(e.getHours()+1);const t=e.toISOString().slice(0,16).replace("T"," ");return window.postMessage({type:"SetPlayerAccountTimeout",timeoutSelected:"CoolOffUntilSelectedDate",timeoutExpiryDate:t},window.location.href),window.postMessage({type:"WidgetNotification",data:{type:"error",message:d("accountBlocked",this.language)}},window.location.href),void this.closePopup()}return this.hasErrors=!0,this.errorMessage=d("invalidOtp",this.language),void this.getConfig()}console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=d("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.closePopup()}closePopup(){this.showPopup=!1,window.dispatchEvent(new CustomEvent("popupClosed",{detail:{message:"User closed the popup"}}))}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await a(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&o(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&s(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"1e969334bcc5ef26826a600bd3743037765ceeb0",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"f85bc272fed6e9ccc54fd21d7f79d81a3f3b9983",class:"OtpPopupOverlay"},t("div",{key:"8ef3f980d3f03034b7f16f97f1f7c4a15f400189",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,d("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.closePopup},d("close",this.language))):t(i,null,t("div",{class:"otp-description"},t("p",null,d("popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage"},this.errorMessage)),t("div",{class:"OtpFieldWrapper"},t("h2",null,d("otpHeading",this.language)),t("div",{class:"OtpField",ref:this.setOtpContainerRef},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.timeLeft<=0})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",d("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},d("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},d("submit",this.language)),t("button",{class:"OtpButton",onClick:this.closePopup},d("close",this.language)))))))}get el(){return r(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};l.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{l as P}
@@ -1 +0,0 @@
1
- export{P as player_step_up_auth}from"./p-00b18944.js";import"./p-c6a4faff.js";