@capgo/capacitor-social-login 8.2.7 → 8.2.8

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.
package/dist/plugin.js CHANGED
@@ -534,77 +534,124 @@ var capacitorCapacitorUpdater = (function (exports, core) {
534
534
  const popup = window.open(url, 'Google Sign In', `width=${width},height=${height},left=${left},top=${top},popup=1`);
535
535
  let popupClosedInterval;
536
536
  let timeoutHandle;
537
+ // Use BroadcastChannel for cross-origin communication (works when postMessage doesn't)
538
+ const channelName = `google_oauth_${nonce || Date.now()}`;
539
+ let broadcastChannel = null;
540
+ try {
541
+ broadcastChannel = new BroadcastChannel(channelName);
542
+ }
543
+ catch (_b) {
544
+ // BroadcastChannel not supported, fall back to postMessage only
545
+ }
537
546
  // This may never return...
538
547
  return new Promise((resolve, reject) => {
539
548
  if (!popup) {
540
549
  reject(new Error('Failed to open popup'));
541
550
  return;
542
551
  }
543
- const handleMessage = (event) => {
544
- var _a, _b, _c, _d;
545
- if (event.origin !== window.location.origin || ((_b = (_a = event.data) === null || _a === void 0 ? void 0 : _a.source) === null || _b === void 0 ? void 0 : _b.startsWith('angular')))
546
- return;
547
- if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.type) === 'oauth-response') {
548
- window.removeEventListener('message', handleMessage);
549
- clearInterval(popupClosedInterval);
550
- clearTimeout(timeoutHandle);
551
- if (this.loginType === 'online') {
552
- const { accessToken, idToken } = event.data;
553
- if (accessToken && idToken) {
554
- const profile = this.parseJwt(idToken);
555
- this.persistStateGoogle(accessToken.token, idToken);
556
- resolve({
557
- provider: 'google',
558
- result: {
559
- accessToken: {
560
- token: accessToken.token,
561
- },
562
- idToken,
563
- profile: {
564
- email: profile.email || null,
565
- familyName: profile.family_name || null,
566
- givenName: profile.given_name || null,
567
- id: profile.sub || null,
568
- name: profile.name || null,
569
- imageUrl: profile.picture || null,
570
- },
571
- responseType: 'online',
572
- },
573
- });
574
- }
575
- }
576
- else {
577
- const { serverAuthCode } = event.data;
552
+ const cleanup = () => {
553
+ window.removeEventListener('message', handleMessage);
554
+ clearInterval(popupClosedInterval);
555
+ clearTimeout(timeoutHandle);
556
+ if (broadcastChannel) {
557
+ broadcastChannel.close();
558
+ }
559
+ };
560
+ const processOAuthResponse = (data) => {
561
+ if (this.loginType === 'online') {
562
+ const { accessToken, idToken } = data;
563
+ if (accessToken && idToken) {
564
+ const profile = this.parseJwt(idToken);
565
+ this.persistStateGoogle(accessToken.token, idToken);
578
566
  resolve({
579
567
  provider: 'google',
580
568
  result: {
581
- responseType: 'offline',
582
- serverAuthCode,
569
+ accessToken: {
570
+ token: accessToken.token,
571
+ },
572
+ idToken,
573
+ profile: {
574
+ email: profile.email || null,
575
+ familyName: profile.family_name || null,
576
+ givenName: profile.given_name || null,
577
+ id: profile.sub || null,
578
+ name: profile.name || null,
579
+ imageUrl: profile.picture || null,
580
+ },
581
+ responseType: 'online',
583
582
  },
584
583
  });
585
584
  }
586
585
  }
586
+ else {
587
+ const { serverAuthCode } = data;
588
+ resolve({
589
+ provider: 'google',
590
+ result: {
591
+ responseType: 'offline',
592
+ serverAuthCode,
593
+ },
594
+ });
595
+ }
596
+ };
597
+ const handleMessage = (event) => {
598
+ var _a, _b, _c, _d;
599
+ if (event.origin !== window.location.origin || ((_b = (_a = event.data) === null || _a === void 0 ? void 0 : _a.source) === null || _b === void 0 ? void 0 : _b.startsWith('angular')))
600
+ return;
601
+ if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.type) === 'oauth-response') {
602
+ cleanup();
603
+ processOAuthResponse(event.data);
604
+ }
587
605
  else if (((_d = event.data) === null || _d === void 0 ? void 0 : _d.type) === 'oauth-error') {
588
- window.removeEventListener('message', handleMessage);
589
- clearInterval(popupClosedInterval);
590
- clearTimeout(timeoutHandle);
606
+ cleanup();
591
607
  const errorMessage = event.data.error || 'User cancelled the OAuth flow';
592
608
  reject(new Error(errorMessage));
593
609
  }
594
610
  // Don't reject for non-OAuth messages, just ignore them
595
611
  };
612
+ // Listen for BroadcastChannel messages
613
+ if (broadcastChannel) {
614
+ broadcastChannel.onmessage = (event) => {
615
+ var _a;
616
+ const data = event.data;
617
+ if ((_a = data === null || data === void 0 ? void 0 : data.source) === null || _a === void 0 ? void 0 : _a.toString().startsWith('angular'))
618
+ return;
619
+ if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-response') {
620
+ cleanup();
621
+ processOAuthResponse(data);
622
+ }
623
+ else if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-error') {
624
+ cleanup();
625
+ const errorMessage = data.error || 'User cancelled the OAuth flow';
626
+ reject(new Error(errorMessage));
627
+ }
628
+ };
629
+ }
596
630
  window.addEventListener('message', handleMessage);
597
631
  // Timeout after 5 minutes
598
632
  timeoutHandle = setTimeout(() => {
599
- clearTimeout(timeoutHandle);
600
- window.removeEventListener('message', handleMessage);
601
- popup.close();
633
+ cleanup();
634
+ try {
635
+ popup.close();
636
+ }
637
+ catch (_a) {
638
+ // Ignore cross-origin errors when closing
639
+ }
602
640
  reject(new Error('OAuth timeout'));
603
641
  }, 300000);
604
642
  popupClosedInterval = setInterval(() => {
605
- if (popup.closed) {
643
+ try {
644
+ // Check if popup is closed - this may throw cross-origin errors for some providers
645
+ if (popup.closed) {
646
+ cleanup();
647
+ reject(new Error('Popup closed'));
648
+ }
649
+ }
650
+ catch (_a) {
651
+ // Cross-origin error when checking popup.closed - this happens when the popup
652
+ // navigates to a third-party OAuth provider with strict security settings.
653
+ // We can't detect if the window was closed, so we rely on timeout and message handlers.
606
654
  clearInterval(popupClosedInterval);
607
- reject(new Error('Popup closed'));
608
655
  }
609
656
  }, 1000);
610
657
  });
@@ -724,52 +771,95 @@ var capacitorCapacitorUpdater = (function (exports, core) {
724
771
  reject(new Error('Unable to open login window. Please allow popups.'));
725
772
  return;
726
773
  }
774
+ // Use BroadcastChannel for cross-origin communication (works when postMessage doesn't)
775
+ const channelName = `oauth2_${state}`;
776
+ let broadcastChannel = null;
777
+ try {
778
+ broadcastChannel = new BroadcastChannel(channelName);
779
+ }
780
+ catch (_a) {
781
+ // BroadcastChannel not supported, fall back to postMessage only
782
+ if (config.logsEnabled) {
783
+ console.log(`[OAuth2:${providerId}] BroadcastChannel not supported, using postMessage only`);
784
+ }
785
+ }
727
786
  const cleanup = (messageHandler, timeoutHandle, intervalHandle) => {
728
787
  window.removeEventListener('message', messageHandler);
729
788
  clearTimeout(timeoutHandle);
730
789
  clearInterval(intervalHandle);
731
- };
732
- const messageHandler = (event) => {
733
- var _a, _b, _c, _d, _e;
734
- if (event.origin !== window.location.origin) {
735
- return;
790
+ if (broadcastChannel) {
791
+ broadcastChannel.close();
736
792
  }
737
- if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === 'oauth-response') {
738
- if (((_b = event.data) === null || _b === void 0 ? void 0 : _b.provider) && event.data.provider !== 'oauth2') {
739
- return;
793
+ };
794
+ const handleOAuthMessage = (data) => {
795
+ if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-response') {
796
+ if ((data === null || data === void 0 ? void 0 : data.provider) && data.provider !== 'oauth2') {
797
+ return false;
740
798
  }
741
799
  // Check providerId matches if present
742
- if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.providerId) && event.data.providerId !== providerId) {
743
- return;
800
+ if ((data === null || data === void 0 ? void 0 : data.providerId) && data.providerId !== providerId) {
801
+ return false;
744
802
  }
745
803
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
746
804
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
747
- const _f = event.data, { provider: _ignoredProvider, type: _ignoredType } = _f, payload = __rest$1(_f, ["provider", "type"]);
805
+ const _a = data, { provider: _ignoredProvider, type: _ignoredType } = _a, payload = __rest$1(_a, ["provider", "type"]);
748
806
  resolve({
749
807
  provider: 'oauth2',
750
808
  result: payload,
751
809
  });
810
+ return true;
752
811
  }
753
- else if (((_d = event.data) === null || _d === void 0 ? void 0 : _d.type) === 'oauth-error') {
754
- if (((_e = event.data) === null || _e === void 0 ? void 0 : _e.provider) && event.data.provider !== 'oauth2') {
755
- return;
812
+ else if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-error') {
813
+ if ((data === null || data === void 0 ? void 0 : data.provider) && data.provider !== 'oauth2') {
814
+ return false;
756
815
  }
757
816
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
758
- reject(new Error(event.data.error || 'OAuth2 login was cancelled.'));
817
+ reject(new Error(data.error || 'OAuth2 login was cancelled.'));
818
+ return true;
759
819
  }
820
+ return false;
821
+ };
822
+ // Listen for BroadcastChannel messages
823
+ if (broadcastChannel) {
824
+ broadcastChannel.onmessage = (event) => {
825
+ handleOAuthMessage(event.data);
826
+ };
827
+ }
828
+ const messageHandler = (event) => {
829
+ if (event.origin !== window.location.origin) {
830
+ return;
831
+ }
832
+ handleOAuthMessage(event.data);
760
833
  };
761
834
  window.addEventListener('message', messageHandler);
762
835
  const timeoutHandle = window.setTimeout(() => {
763
- window.removeEventListener('message', messageHandler);
764
- popup.close();
836
+ cleanup(messageHandler, timeoutHandle, popupClosedInterval);
837
+ try {
838
+ popup.close();
839
+ }
840
+ catch (_a) {
841
+ // Ignore cross-origin errors when closing
842
+ }
765
843
  reject(new Error('OAuth2 login timed out.'));
766
844
  }, 300000);
767
845
  const popupClosedInterval = window.setInterval(() => {
768
- if (popup.closed) {
769
- window.removeEventListener('message', messageHandler);
846
+ try {
847
+ // Check if popup is closed - this may throw cross-origin errors for some providers
848
+ if (popup.closed) {
849
+ cleanup(messageHandler, timeoutHandle, popupClosedInterval);
850
+ reject(new Error('OAuth2 login window was closed.'));
851
+ }
852
+ }
853
+ catch (_a) {
854
+ // Cross-origin error when checking popup.closed - this happens when the popup
855
+ // navigates to a third-party OAuth provider with strict security settings.
856
+ // We can't detect if the window was closed, so we just rely on the timeout
857
+ // and message handlers. Clear the interval to avoid repeated errors.
770
858
  clearInterval(popupClosedInterval);
771
- clearTimeout(timeoutHandle);
772
- reject(new Error('OAuth2 login window was closed.'));
859
+ if (config.logsEnabled) {
860
+ console.log(`[OAuth2:${providerId}] Cannot check popup.closed due to cross-origin restrictions. ` +
861
+ 'Relying on message handlers and timeout.');
862
+ }
773
863
  }
774
864
  }, 1000);
775
865
  });
@@ -1126,48 +1216,83 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1126
1216
  reject(new Error('Unable to open login window. Please allow popups.'));
1127
1217
  return;
1128
1218
  }
1219
+ // Use BroadcastChannel for cross-origin communication (works when postMessage doesn't)
1220
+ const channelName = `twitter_oauth_${state}`;
1221
+ let broadcastChannel = null;
1222
+ try {
1223
+ broadcastChannel = new BroadcastChannel(channelName);
1224
+ }
1225
+ catch (_a) {
1226
+ // BroadcastChannel not supported, fall back to postMessage only
1227
+ }
1129
1228
  const cleanup = (messageHandler, timeoutHandle, intervalHandle) => {
1130
1229
  window.removeEventListener('message', messageHandler);
1131
1230
  clearTimeout(timeoutHandle);
1132
1231
  clearInterval(intervalHandle);
1133
- };
1134
- const messageHandler = (event) => {
1135
- var _a, _b, _c, _d;
1136
- if (event.origin !== window.location.origin) {
1137
- return;
1232
+ if (broadcastChannel) {
1233
+ broadcastChannel.close();
1138
1234
  }
1139
- if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === 'oauth-response') {
1140
- if (((_b = event.data) === null || _b === void 0 ? void 0 : _b.provider) && event.data.provider !== 'twitter') {
1141
- return;
1235
+ };
1236
+ const handleOAuthMessage = (data) => {
1237
+ if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-response') {
1238
+ if ((data === null || data === void 0 ? void 0 : data.provider) && data.provider !== 'twitter') {
1239
+ return false;
1142
1240
  }
1143
1241
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1144
1242
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1145
- const _e = event.data, { provider: _ignoredProvider } = _e, payload = __rest(_e, ["provider"]);
1243
+ const _a = data, { provider: _ignoredProvider } = _a, payload = __rest(_a, ["provider"]);
1146
1244
  resolve({
1147
1245
  provider: 'twitter',
1148
1246
  result: payload,
1149
1247
  });
1248
+ return true;
1150
1249
  }
1151
- else if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.type) === 'oauth-error') {
1152
- if (((_d = event.data) === null || _d === void 0 ? void 0 : _d.provider) && event.data.provider !== 'twitter') {
1153
- return;
1250
+ else if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-error') {
1251
+ if ((data === null || data === void 0 ? void 0 : data.provider) && data.provider !== 'twitter') {
1252
+ return false;
1154
1253
  }
1155
1254
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1156
- reject(new Error(event.data.error || 'Twitter login was cancelled.'));
1255
+ reject(new Error(data.error || 'Twitter login was cancelled.'));
1256
+ return true;
1257
+ }
1258
+ return false;
1259
+ };
1260
+ // Listen for BroadcastChannel messages
1261
+ if (broadcastChannel) {
1262
+ broadcastChannel.onmessage = (event) => {
1263
+ handleOAuthMessage(event.data);
1264
+ };
1265
+ }
1266
+ const messageHandler = (event) => {
1267
+ if (event.origin !== window.location.origin) {
1268
+ return;
1157
1269
  }
1270
+ handleOAuthMessage(event.data);
1158
1271
  };
1159
1272
  window.addEventListener('message', messageHandler);
1160
1273
  const timeoutHandle = window.setTimeout(() => {
1161
- window.removeEventListener('message', messageHandler);
1162
- popup.close();
1274
+ cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1275
+ try {
1276
+ popup.close();
1277
+ }
1278
+ catch (_a) {
1279
+ // Ignore cross-origin errors when closing
1280
+ }
1163
1281
  reject(new Error('Twitter login timed out.'));
1164
1282
  }, 300000);
1165
1283
  const popupClosedInterval = window.setInterval(() => {
1166
- if (popup.closed) {
1167
- window.removeEventListener('message', messageHandler);
1284
+ try {
1285
+ // Check if popup is closed - this may throw cross-origin errors for some providers
1286
+ if (popup.closed) {
1287
+ cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1288
+ reject(new Error('Twitter login window was closed.'));
1289
+ }
1290
+ }
1291
+ catch (_a) {
1292
+ // Cross-origin error when checking popup.closed - this happens when the popup
1293
+ // navigates to a third-party OAuth provider with strict security settings.
1294
+ // We can't detect if the window was closed, so we rely on timeout and message handlers.
1168
1295
  clearInterval(popupClosedInterval);
1169
- clearTimeout(timeoutHandle);
1170
- reject(new Error('Twitter login window was closed.'));
1171
1296
  }
1172
1297
  }, 1000);
1173
1298
  });
@@ -1418,7 +1543,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1418
1543
  }
1419
1544
  }
1420
1545
  async handleOAuthRedirect() {
1421
- var _a, _b, _c;
1546
+ var _a;
1422
1547
  const url = new URL(window.location.href);
1423
1548
  const stateRaw = localStorage.getItem(SocialLoginWeb.OAUTH_STATE_KEY);
1424
1549
  let provider = null;
@@ -1429,7 +1554,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1429
1554
  provider = (_a = parsed.provider) !== null && _a !== void 0 ? _a : null;
1430
1555
  state = parsed.state;
1431
1556
  }
1432
- catch (_d) {
1557
+ catch (_b) {
1433
1558
  provider = stateRaw === 'true' ? 'google' : null;
1434
1559
  }
1435
1560
  }
@@ -1449,16 +1574,53 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1449
1574
  if (!result) {
1450
1575
  return;
1451
1576
  }
1577
+ // Build the message to send
1578
+ let message;
1452
1579
  if ('error' in result) {
1453
1580
  const resolvedProvider = provider !== null && provider !== void 0 ? provider : null;
1454
- (_b = window.opener) === null || _b === void 0 ? void 0 : _b.postMessage({
1581
+ message = {
1455
1582
  type: 'oauth-error',
1456
1583
  provider: resolvedProvider,
1457
1584
  error: result.error,
1458
- }, window.location.origin);
1585
+ };
1459
1586
  }
1460
1587
  else {
1461
- (_c = window.opener) === null || _c === void 0 ? void 0 : _c.postMessage(Object.assign({ type: 'oauth-response', provider: result.provider }, result.result), window.location.origin);
1588
+ message = Object.assign({ type: 'oauth-response', provider: result.provider }, result.result);
1589
+ }
1590
+ // Try postMessage first (works when window.opener is accessible)
1591
+ try {
1592
+ if (window.opener) {
1593
+ window.opener.postMessage(message, window.location.origin);
1594
+ }
1595
+ }
1596
+ catch (_c) {
1597
+ // Cross-origin error - window.opener may not be accessible
1598
+ console.log('postMessage to opener failed, using BroadcastChannel');
1599
+ }
1600
+ // Also use BroadcastChannel as a fallback (works across same-origin windows
1601
+ // even when window.opener is not accessible due to cross-origin navigation)
1602
+ try {
1603
+ // Determine the channel name based on provider and state
1604
+ let channelName = null;
1605
+ if (provider === 'oauth2' && state) {
1606
+ channelName = `oauth2_${state}`;
1607
+ }
1608
+ else if (provider === 'twitter' && state) {
1609
+ channelName = `twitter_oauth_${state}`;
1610
+ }
1611
+ else if (provider === 'google') {
1612
+ // Google uses nonce which we can't easily recover here, but try anyway
1613
+ // The parent window will have created a channel with a nonce-based name
1614
+ }
1615
+ if (channelName) {
1616
+ const channel = new BroadcastChannel(channelName);
1617
+ channel.postMessage(message);
1618
+ channel.close();
1619
+ }
1620
+ }
1621
+ catch (_d) {
1622
+ // BroadcastChannel not supported or other error
1623
+ console.log('BroadcastChannel not available');
1462
1624
  }
1463
1625
  window.close();
1464
1626
  }