@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.
- package/README.md +21 -0
- package/android/src/main/java/ee/forgr/capacitor/social/login/FacebookProvider.java +2 -1
- package/android/src/main/java/ee/forgr/capacitor/social/login/GoogleProvider.java +6 -0
- package/android/src/main/java/ee/forgr/capacitor/social/login/OAuth2LoginActivity.java +5 -3
- package/android/src/main/java/ee/forgr/capacitor/social/login/OAuth2Provider.java +25 -2
- package/android/src/main/java/ee/forgr/capacitor/social/login/SocialLoginPlugin.java +1 -1
- package/android/src/main/java/ee/forgr/capacitor/social/login/TwitterLoginActivity.java +5 -3
- package/android/src/main/java/ee/forgr/capacitor/social/login/TwitterProvider.java +25 -2
- package/dist/docs.json +1 -1
- package/dist/esm/apple-provider.js +4 -1
- package/dist/esm/apple-provider.js.map +1 -1
- package/dist/esm/definitions.d.ts +17 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/errors.d.ts +8 -0
- package/dist/esm/errors.js +30 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/facebook-provider.d.ts +2 -1
- package/dist/esm/facebook-provider.js +91 -26
- package/dist/esm/facebook-provider.js.map +1 -1
- package/dist/esm/google-provider.d.ts +1 -1
- package/dist/esm/google-provider.js +4 -3
- package/dist/esm/google-provider.js.map +1 -1
- package/dist/esm/oauth2-provider.d.ts +5 -0
- package/dist/esm/oauth2-provider.js +42 -3
- package/dist/esm/oauth2-provider.js.map +1 -1
- package/dist/esm/twitter-provider.js +5 -4
- package/dist/esm/twitter-provider.js.map +1 -1
- package/dist/esm/web.js +4 -6
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +174 -43
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +174 -43
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/SocialLoginPlugin/SocialLoginPlugin.swift +46 -2
- 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
|
-
|
|
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
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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
|
-
|
|
2082
|
-
|
|
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
|
|
2386
|
+
throw inferUserCancelledError(result.error);
|
|
2256
2387
|
}
|
|
2257
2388
|
return result;
|
|
2258
2389
|
}
|