@capgo/capacitor-social-login 8.3.18 → 8.3.20

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.
Files changed (35) hide show
  1. package/README.md +21 -0
  2. package/android/src/main/java/ee/forgr/capacitor/social/login/FacebookProvider.java +2 -1
  3. package/android/src/main/java/ee/forgr/capacitor/social/login/GoogleProvider.java +6 -0
  4. package/android/src/main/java/ee/forgr/capacitor/social/login/OAuth2LoginActivity.java +5 -3
  5. package/android/src/main/java/ee/forgr/capacitor/social/login/OAuth2Provider.java +25 -2
  6. package/android/src/main/java/ee/forgr/capacitor/social/login/SocialLoginPlugin.java +1 -1
  7. package/android/src/main/java/ee/forgr/capacitor/social/login/TwitterLoginActivity.java +5 -3
  8. package/android/src/main/java/ee/forgr/capacitor/social/login/TwitterProvider.java +25 -2
  9. package/dist/docs.json +1 -1
  10. package/dist/esm/apple-provider.js +4 -1
  11. package/dist/esm/apple-provider.js.map +1 -1
  12. package/dist/esm/definitions.d.ts +17 -0
  13. package/dist/esm/definitions.js.map +1 -1
  14. package/dist/esm/errors.d.ts +8 -0
  15. package/dist/esm/errors.js +30 -0
  16. package/dist/esm/errors.js.map +1 -0
  17. package/dist/esm/facebook-provider.d.ts +2 -1
  18. package/dist/esm/facebook-provider.js +91 -26
  19. package/dist/esm/facebook-provider.js.map +1 -1
  20. package/dist/esm/google-provider.d.ts +1 -1
  21. package/dist/esm/google-provider.js +4 -3
  22. package/dist/esm/google-provider.js.map +1 -1
  23. package/dist/esm/oauth2-provider.d.ts +5 -0
  24. package/dist/esm/oauth2-provider.js +42 -3
  25. package/dist/esm/oauth2-provider.js.map +1 -1
  26. package/dist/esm/twitter-provider.js +5 -4
  27. package/dist/esm/twitter-provider.js.map +1 -1
  28. package/dist/esm/web.js +4 -6
  29. package/dist/esm/web.js.map +1 -1
  30. package/dist/plugin.cjs.js +174 -43
  31. package/dist/plugin.cjs.js.map +1 -1
  32. package/dist/plugin.js +174 -43
  33. package/dist/plugin.js.map +1 -1
  34. package/ios/Sources/SocialLoginPlugin/SocialLoginPlugin.swift +46 -2
  35. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -336,6 +336,36 @@ var capacitorCapacitorUpdater = (function (exports, core) {
336
336
  }
337
337
  BaseSocialLogin.OAUTH_STATE_KEY = 'social_login_oauth_pending';
338
338
 
339
+ const USER_CANCELLED_CODE = 'USER_CANCELLED';
340
+ const CANCELLED_PATTERNS = [
341
+ 'access_denied',
342
+ 'access denied',
343
+ 'user_cancelled_authorize',
344
+ 'user_cancelled',
345
+ 'user cancelled',
346
+ 'user canceled',
347
+ 'login cancelled',
348
+ 'login canceled',
349
+ 'popup closed',
350
+ 'window was closed',
351
+ ];
352
+ function createUserCancelledError(message) {
353
+ const error = new Error(message);
354
+ error.code = USER_CANCELLED_CODE;
355
+ return error;
356
+ }
357
+ /**
358
+ * Detects cancellation-like messages and marks them with USER_CANCELLED.
359
+ * Falls back to a regular Error when the message doesn't look like a user cancellation.
360
+ */
361
+ function inferUserCancelledError(message) {
362
+ const normalized = message.toLowerCase();
363
+ if (CANCELLED_PATTERNS.some((pattern) => normalized.includes(pattern))) {
364
+ return createUserCancelledError(message);
365
+ }
366
+ return new Error(message);
367
+ }
368
+
339
369
  class AppleSocialLogin extends BaseSocialLogin {
340
370
  constructor() {
341
371
  super(...arguments);
@@ -396,7 +426,9 @@ var capacitorCapacitorUpdater = (function (exports, core) {
396
426
  resolve({ provider: 'apple', result });
397
427
  })
398
428
  .catch((error) => {
399
- reject(error);
429
+ var _a, _b, _c;
430
+ const message = (_c = (_b = (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error === null || error === void 0 ? void 0 : error.localizedDescription) !== null && _b !== void 0 ? _b : error === null || error === void 0 ? void 0 : error.error) !== null && _c !== void 0 ? _c : 'Apple login failed';
431
+ reject(inferUserCancelledError(message));
400
432
  });
401
433
  });
402
434
  }
@@ -455,37 +487,69 @@ var capacitorCapacitorUpdater = (function (exports, core) {
455
487
  throw new Error('Facebook App ID not set. Call initialize() first.');
456
488
  }
457
489
  return new Promise((resolve, reject) => {
490
+ var _a;
491
+ let settled = false;
492
+ let waitingForStatus = false;
493
+ const resolveWithProfile = (authResponse) => {
494
+ if (settled)
495
+ return;
496
+ if (!(authResponse === null || authResponse === void 0 ? void 0 : authResponse.accessToken) || !authResponse.userID) {
497
+ settled = true;
498
+ reject(new Error('Facebook login failed'));
499
+ return;
500
+ }
501
+ const accessToken = authResponse.accessToken;
502
+ const userId = authResponse.userID;
503
+ FB.api('/me', { fields: 'id,name,email,picture' }, (userInfo) => {
504
+ var _a, _b;
505
+ settled = true;
506
+ const result = {
507
+ accessToken: {
508
+ token: accessToken,
509
+ userId,
510
+ },
511
+ profile: {
512
+ userID: userInfo.id,
513
+ name: userInfo.name,
514
+ email: userInfo.email || null,
515
+ imageURL: ((_b = (_a = userInfo.picture) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.url) || null,
516
+ friendIDs: [],
517
+ birthday: null,
518
+ ageRange: null,
519
+ gender: null,
520
+ location: null,
521
+ hometown: null,
522
+ profileURL: null,
523
+ },
524
+ idToken: null,
525
+ };
526
+ resolve({ provider: 'facebook', result });
527
+ });
528
+ };
529
+ const waitForConnected = () => {
530
+ if (settled || waitingForStatus)
531
+ return;
532
+ waitingForStatus = true;
533
+ this.waitForConnection()
534
+ .then((statusResponse) => resolveWithProfile(statusResponse.authResponse))
535
+ .catch((error) => {
536
+ if (settled)
537
+ return;
538
+ settled = true;
539
+ reject(error);
540
+ });
541
+ };
458
542
  FB.login((response) => {
459
543
  if (response.status === 'connected') {
460
- FB.api('/me', { fields: 'id,name,email,picture' }, (userInfo) => {
461
- var _a, _b;
462
- const result = {
463
- accessToken: {
464
- token: response.authResponse.accessToken,
465
- userId: response.authResponse.userID,
466
- },
467
- profile: {
468
- userID: userInfo.id,
469
- name: userInfo.name,
470
- email: userInfo.email || null,
471
- imageURL: ((_b = (_a = userInfo.picture) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.url) || null,
472
- friendIDs: [],
473
- birthday: null,
474
- ageRange: null,
475
- gender: null,
476
- location: null,
477
- hometown: null,
478
- profileURL: null,
479
- },
480
- idToken: null,
481
- };
482
- resolve({ provider: 'facebook', result });
483
- });
544
+ resolveWithProfile(response.authResponse);
545
+ }
546
+ else if (response.status === 'not_authorized' || response.status === 'unknown') {
547
+ reject(createUserCancelledError('Facebook login was cancelled.'));
484
548
  }
485
549
  else {
486
- reject(new Error('Facebook login failed'));
550
+ waitForConnected();
487
551
  }
488
- }, { scope: options.permissions.join(',') });
552
+ }, ((_a = options.permissions) === null || _a === void 0 ? void 0 : _a.length) ? { scope: options.permissions.join(',') } : undefined);
489
553
  });
490
554
  }
491
555
  async logout() {
@@ -516,6 +580,38 @@ var capacitorCapacitorUpdater = (function (exports, core) {
516
580
  async refresh(options) {
517
581
  await this.login(options);
518
582
  }
583
+ waitForConnection(timeoutMs = 120000, pollIntervalMs = 500) {
584
+ const start = Date.now();
585
+ return new Promise((resolve, reject) => {
586
+ let finished = false;
587
+ const pollStatus = () => {
588
+ if (finished)
589
+ return;
590
+ FB.getLoginStatus((response) => {
591
+ var _a;
592
+ if (finished)
593
+ return;
594
+ if (response.status === 'connected' && ((_a = response.authResponse) === null || _a === void 0 ? void 0 : _a.accessToken)) {
595
+ finished = true;
596
+ resolve(response);
597
+ return;
598
+ }
599
+ if (response.status === 'not_authorized' || response.status === 'unknown') {
600
+ finished = true;
601
+ reject(createUserCancelledError('Facebook login was cancelled.'));
602
+ return;
603
+ }
604
+ if (Date.now() - start >= timeoutMs) {
605
+ finished = true;
606
+ reject(new Error('Facebook login failed or timed out'));
607
+ return;
608
+ }
609
+ setTimeout(pollStatus, pollIntervalMs);
610
+ });
611
+ };
612
+ pollStatus();
613
+ });
614
+ }
519
615
  async loadFacebookScript(locale) {
520
616
  if (this.scriptLoaded)
521
617
  return;
@@ -925,7 +1021,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
925
1021
  else if (((_d = event.data) === null || _d === void 0 ? void 0 : _d.type) === 'oauth-error') {
926
1022
  cleanup(true);
927
1023
  const errorMessage = event.data.error || 'User cancelled the OAuth flow';
928
- reject(new Error(errorMessage));
1024
+ reject(inferUserCancelledError(errorMessage));
929
1025
  }
930
1026
  // Don't reject for non-OAuth messages, just ignore them
931
1027
  };
@@ -943,7 +1039,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
943
1039
  else if ((data === null || data === void 0 ? void 0 : data.type) === 'oauth-error') {
944
1040
  cleanup(true);
945
1041
  const errorMessage = data.error || 'User cancelled the OAuth flow';
946
- reject(new Error(errorMessage));
1042
+ reject(inferUserCancelledError(errorMessage));
947
1043
  }
948
1044
  };
949
1045
  }
@@ -958,7 +1054,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
958
1054
  // Check if popup is closed - this may throw cross-origin errors for some providers
959
1055
  if (popup.closed) {
960
1056
  cleanup();
961
- reject(new Error('Popup closed'));
1057
+ reject(createUserCancelledError('Popup closed'));
962
1058
  }
963
1059
  }
964
1060
  catch (_a) {
@@ -978,10 +1074,13 @@ var capacitorCapacitorUpdater = (function (exports, core) {
978
1074
  */
979
1075
  class OAuth2SocialLogin extends BaseSocialLogin {
980
1076
  constructor() {
981
- super(...arguments);
1077
+ super();
982
1078
  this.providers = new Map();
983
1079
  this.TOKENS_KEY_PREFIX = 'capgo_social_login_oauth2_tokens_';
984
1080
  this.STATE_PREFIX = 'capgo_social_login_oauth2_state_';
1081
+ this.CONFIG_KEY_PREFIX = 'capgo_social_login_oauth2_config_';
1082
+ // Restore configurations from localStorage for popup window context
1083
+ this.restoreConfigurationsFromStorage();
985
1084
  }
986
1085
  normalizeScopeValue(scope) {
987
1086
  if (!scope)
@@ -1064,6 +1163,8 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1064
1163
  logoutUrl: config.logoutUrl,
1065
1164
  });
1066
1165
  }
1166
+ // Persist updated configuration after discovery
1167
+ this.persistConfiguration(providerId, config);
1067
1168
  }
1068
1169
  /**
1069
1170
  * Initialize multiple OAuth2 providers
@@ -1084,6 +1185,8 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1084
1185
  }
1085
1186
  // Pre-resolve discovery on web if issuerUrl is provided.
1086
1187
  await this.ensureDiscovered(providerId);
1188
+ // Persist configuration to localStorage so it's available in popup window context
1189
+ this.persistConfiguration(providerId, internalConfig);
1087
1190
  }
1088
1191
  }
1089
1192
  getProvider(providerId) {
@@ -1096,6 +1199,37 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1096
1199
  getTokensKey(providerId) {
1097
1200
  return `${this.TOKENS_KEY_PREFIX}${providerId}`;
1098
1201
  }
1202
+ getConfigKey(providerId) {
1203
+ return `${this.CONFIG_KEY_PREFIX}${providerId}`;
1204
+ }
1205
+ persistConfiguration(providerId, config) {
1206
+ try {
1207
+ localStorage.setItem(this.getConfigKey(providerId), JSON.stringify(config));
1208
+ }
1209
+ catch (err) {
1210
+ console.warn(`Failed to persist OAuth2 configuration for provider '${providerId}'`, err);
1211
+ }
1212
+ }
1213
+ restoreConfigurationsFromStorage() {
1214
+ // Restore all provider configurations from localStorage
1215
+ // This is needed for popup window context where the parent's in-memory state is not available
1216
+ const keys = Object.keys(localStorage);
1217
+ for (const key of keys) {
1218
+ if (key.startsWith(this.CONFIG_KEY_PREFIX)) {
1219
+ const providerId = key.substring(this.CONFIG_KEY_PREFIX.length);
1220
+ try {
1221
+ const raw = localStorage.getItem(key);
1222
+ if (raw) {
1223
+ const config = JSON.parse(raw);
1224
+ this.providers.set(providerId, config);
1225
+ }
1226
+ }
1227
+ catch (err) {
1228
+ console.warn(`Failed to restore OAuth2 configuration for provider '${providerId}'`, err);
1229
+ }
1230
+ }
1231
+ }
1232
+ }
1099
1233
  async login(options) {
1100
1234
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1101
1235
  const { providerId } = options;
@@ -1212,7 +1346,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1212
1346
  return false;
1213
1347
  }
1214
1348
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1215
- reject(new Error(data.error || 'OAuth2 login was cancelled.'));
1349
+ reject(inferUserCancelledError(data.error || 'OAuth2 login was cancelled.'));
1216
1350
  return true;
1217
1351
  }
1218
1352
  return false;
@@ -1245,7 +1379,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1245
1379
  // Check if popup is closed - this may throw cross-origin errors for some providers
1246
1380
  if (popup.closed) {
1247
1381
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1248
- reject(new Error('OAuth2 login window was closed.'));
1382
+ reject(createUserCancelledError('OAuth2 login window was closed.'));
1249
1383
  }
1250
1384
  }
1251
1385
  catch (_a) {
@@ -1671,6 +1805,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1671
1805
  const codeVerifier = (_e = options.codeVerifier) !== null && _e !== void 0 ? _e : this.generateCodeVerifier();
1672
1806
  const codeChallenge = await this.generateCodeChallenge(codeVerifier);
1673
1807
  this.persistPendingLogin(state, {
1808
+ clientId: this.clientId,
1674
1809
  codeVerifier,
1675
1810
  redirectUri,
1676
1811
  scopes,
@@ -1738,7 +1873,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1738
1873
  return false;
1739
1874
  }
1740
1875
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1741
- reject(new Error(data.error || 'Twitter login was cancelled.'));
1876
+ reject(inferUserCancelledError(data.error || 'Twitter login was cancelled.'));
1742
1877
  return true;
1743
1878
  }
1744
1879
  return false;
@@ -1771,7 +1906,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1771
1906
  // Check if popup is closed - this may throw cross-origin errors for some providers
1772
1907
  if (popup.closed) {
1773
1908
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
1774
- reject(new Error('Twitter login window was closed.'));
1909
+ reject(createUserCancelledError('Twitter login window was closed.'));
1775
1910
  }
1776
1911
  }
1777
1912
  catch (_a) {
@@ -1876,10 +2011,9 @@ var capacitorCapacitorUpdater = (function (exports, core) {
1876
2011
  }
1877
2012
  }
1878
2013
  async exchangeAuthorizationCode(code, pending) {
1879
- var _a;
1880
2014
  const params = new URLSearchParams({
1881
2015
  grant_type: 'authorization_code',
1882
- client_id: (_a = this.clientId) !== null && _a !== void 0 ? _a : '',
2016
+ client_id: pending.clientId,
1883
2017
  code,
1884
2018
  redirect_uri: pending.redirectUri,
1885
2019
  code_verifier: pending.codeVerifier,
@@ -2078,11 +2212,8 @@ var capacitorCapacitorUpdater = (function (exports, core) {
2078
2212
  let message;
2079
2213
  if ('error' in result) {
2080
2214
  const resolvedProvider = (_a = parsed.provider) !== null && _a !== void 0 ? _a : null;
2081
- message = {
2082
- type: 'oauth-error',
2083
- provider: resolvedProvider,
2084
- error: result.error,
2085
- };
2215
+ const error = inferUserCancelledError(result.error);
2216
+ message = Object.assign({ type: 'oauth-error', provider: resolvedProvider, error: error.message }, (error.code ? { code: error.code } : null));
2086
2217
  }
2087
2218
  else {
2088
2219
  message = Object.assign({ type: 'oauth-response', provider: result.provider }, result.result);
@@ -2252,7 +2383,7 @@ var capacitorCapacitorUpdater = (function (exports, core) {
2252
2383
  if (!result)
2253
2384
  return null;
2254
2385
  if ('error' in result) {
2255
- throw new Error(result.error);
2386
+ throw inferUserCancelledError(result.error);
2256
2387
  }
2257
2388
  return result;
2258
2389
  }