@opexa/portal-sdk 0.59.95 → 0.59.96
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/{chunk-RCMZBLLX.js → chunk-MJLXQ6HC.js} +31 -18
- package/dist/chunk-MJLXQ6HC.js.map +1 -0
- package/dist/index.cjs +169 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +138 -27
- package/dist/index.js.map +1 -1
- package/dist/services/index.cjs +26 -20
- package/dist/services/index.cjs.map +1 -1
- package/dist/services/index.js +1 -1
- package/package.json +9 -2
- package/dist/chunk-RCMZBLLX.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint } from './chunk-
|
|
1
|
+
import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint, isIOSPlatform } from './chunk-MJLXQ6HC.js';
|
|
2
2
|
import { GraphQLClient, isPlainObject } from './chunk-7APXFZ5G.js';
|
|
3
3
|
import './chunk-WVFSGB7Y.js';
|
|
4
4
|
import { ObjectId } from '@opexa/object-id';
|
|
@@ -336,6 +336,48 @@ function pollable(func, config) {
|
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
// src/sdk/refresh-token-store.ts
|
|
340
|
+
var PreferencesRefreshTokenStore = class {
|
|
341
|
+
constructor(key, logger) {
|
|
342
|
+
this.key = key;
|
|
343
|
+
this.logger = logger;
|
|
344
|
+
}
|
|
345
|
+
async preferences() {
|
|
346
|
+
const { Preferences } = await import('@capacitor/preferences');
|
|
347
|
+
return Preferences;
|
|
348
|
+
}
|
|
349
|
+
async get() {
|
|
350
|
+
if (!isIOSPlatform()) return null;
|
|
351
|
+
try {
|
|
352
|
+
const { value } = await (await this.preferences()).get({ key: this.key });
|
|
353
|
+
return value ?? null;
|
|
354
|
+
} catch (err) {
|
|
355
|
+
this.logger.error(`Failed to read the refresh token: ${err}`);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async set(token) {
|
|
360
|
+
if (!isIOSPlatform()) return;
|
|
361
|
+
try {
|
|
362
|
+
await (await this.preferences()).set({ key: this.key, value: token });
|
|
363
|
+
} catch (err) {
|
|
364
|
+
this.logger.error(`Failed to persist the refresh token: ${err}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
async remove() {
|
|
368
|
+
if (!isIOSPlatform()) return;
|
|
369
|
+
try {
|
|
370
|
+
await (await this.preferences()).remove({ key: this.key });
|
|
371
|
+
} catch (err) {
|
|
372
|
+
this.logger.error(`Failed to clear the refresh token: ${err}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
function createRefreshTokenStore(logger, sessionPrefix) {
|
|
377
|
+
const key = sessionPrefix ? `${sessionPrefix}/session/refresh-token` : "session/refresh-token";
|
|
378
|
+
return new PreferencesRefreshTokenStore(key, logger);
|
|
379
|
+
}
|
|
380
|
+
|
|
339
381
|
// src/sdk/session-manager.ts
|
|
340
382
|
var SessionManager = class {
|
|
341
383
|
logger;
|
|
@@ -345,17 +387,22 @@ var SessionManager = class {
|
|
|
345
387
|
walletService;
|
|
346
388
|
_refreshing = false;
|
|
347
389
|
/*
|
|
348
|
-
* v4 access tokens
|
|
349
|
-
*
|
|
350
|
-
*
|
|
390
|
+
* v4 access tokens live in memory only, so an XSS-readable storage layer
|
|
391
|
+
* never holds a live one. Re-minted from the HttpOnly cookie, or from
|
|
392
|
+
* `refreshTokenStore` on iOS.
|
|
351
393
|
*/
|
|
352
394
|
v4AccessToken = null;
|
|
353
395
|
v4AccessTokenExpiresAt = null;
|
|
354
396
|
v4RefreshPromise = null;
|
|
397
|
+
refreshTokenStore;
|
|
355
398
|
constructor(config) {
|
|
356
399
|
this.authService = config.authService;
|
|
357
400
|
this.walletService = config.walletService;
|
|
358
401
|
this.logger = config.logger;
|
|
402
|
+
this.refreshTokenStore = createRefreshTokenStore(
|
|
403
|
+
config.logger,
|
|
404
|
+
config.sessionPrefix
|
|
405
|
+
);
|
|
359
406
|
if (config.sessionPrefix) {
|
|
360
407
|
this.storageKey = `${config.sessionPrefix}/${this.storageKey}`;
|
|
361
408
|
this.platformStorageKey = `${config.sessionPrefix}/${this.platformStorageKey}`;
|
|
@@ -367,7 +414,7 @@ var SessionManager = class {
|
|
|
367
414
|
set refreshing(value) {
|
|
368
415
|
this._refreshing = value;
|
|
369
416
|
}
|
|
370
|
-
persist(data, version) {
|
|
417
|
+
async persist(data, version) {
|
|
371
418
|
const now = /* @__PURE__ */ new Date();
|
|
372
419
|
if (version === 4) {
|
|
373
420
|
if (!data.session || !data.accessToken) {
|
|
@@ -378,6 +425,9 @@ var SessionManager = class {
|
|
|
378
425
|
}
|
|
379
426
|
this.v4AccessToken = data.accessToken;
|
|
380
427
|
this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
|
|
428
|
+
if (data.refreshToken) {
|
|
429
|
+
await this.refreshTokenStore.set(data.refreshToken);
|
|
430
|
+
}
|
|
381
431
|
localStorage.setItem(
|
|
382
432
|
this.storageKey,
|
|
383
433
|
JSON.stringify({ version, session: data.session })
|
|
@@ -440,7 +490,8 @@ var SessionManager = class {
|
|
|
440
490
|
maxAttempt: 5
|
|
441
491
|
})();
|
|
442
492
|
if (!r1.ok) return r1;
|
|
443
|
-
if (!this.persist(r1.data, version))
|
|
493
|
+
if (!await this.persist(r1.data, version))
|
|
494
|
+
return this.malformedResponseError();
|
|
444
495
|
return {
|
|
445
496
|
ok: true,
|
|
446
497
|
data: null
|
|
@@ -449,7 +500,7 @@ var SessionManager = class {
|
|
|
449
500
|
if (input.type === "MOBILE_NUMBER") {
|
|
450
501
|
const res2 = await this.authService.createSession(input, version);
|
|
451
502
|
if (res2.ok) {
|
|
452
|
-
if (!this.persist(res2.data, version))
|
|
503
|
+
if (!await this.persist(res2.data, version))
|
|
453
504
|
return this.malformedResponseError();
|
|
454
505
|
return {
|
|
455
506
|
ok: true,
|
|
@@ -468,7 +519,7 @@ var SessionManager = class {
|
|
|
468
519
|
version
|
|
469
520
|
);
|
|
470
521
|
if (res2.ok) {
|
|
471
|
-
if (!this.persist(res2.data, version))
|
|
522
|
+
if (!await this.persist(res2.data, version))
|
|
472
523
|
return this.malformedResponseError();
|
|
473
524
|
return {
|
|
474
525
|
ok: true,
|
|
@@ -481,7 +532,7 @@ var SessionManager = class {
|
|
|
481
532
|
localStorage.setItem(this.platformStorageKey, "CABINET");
|
|
482
533
|
const res2 = await this.authService.createSession(input, version);
|
|
483
534
|
if (res2.ok) {
|
|
484
|
-
if (!this.persist(res2.data, version))
|
|
535
|
+
if (!await this.persist(res2.data, version))
|
|
485
536
|
return this.malformedResponseError();
|
|
486
537
|
return {
|
|
487
538
|
ok: true,
|
|
@@ -500,7 +551,8 @@ var SessionManager = class {
|
|
|
500
551
|
}
|
|
501
552
|
};
|
|
502
553
|
}
|
|
503
|
-
if (!this.persist(res.data, version))
|
|
554
|
+
if (!await this.persist(res.data, version))
|
|
555
|
+
return this.malformedResponseError();
|
|
504
556
|
return {
|
|
505
557
|
ok: true,
|
|
506
558
|
data: null
|
|
@@ -511,7 +563,7 @@ var SessionManager = class {
|
|
|
511
563
|
if (res.ok) {
|
|
512
564
|
if (this.isServer) {
|
|
513
565
|
this.logger.warn("'localStorage' is not available on the server.");
|
|
514
|
-
} else if (!this.persist(res.data, 1)) {
|
|
566
|
+
} else if (!await this.persist(res.data, 1)) {
|
|
515
567
|
return this.malformedResponseError();
|
|
516
568
|
}
|
|
517
569
|
return { ok: true };
|
|
@@ -701,14 +753,31 @@ var SessionManager = class {
|
|
|
701
753
|
}
|
|
702
754
|
async requestV4Refresh(session) {
|
|
703
755
|
this.logger.info("Refreshing session...");
|
|
756
|
+
let refreshToken;
|
|
757
|
+
if (isIOSPlatform()) {
|
|
758
|
+
refreshToken = await this.refreshTokenStore.get() ?? void 0;
|
|
759
|
+
if (!refreshToken) {
|
|
760
|
+
this.logger.warn("No stored refresh token. Session expired.");
|
|
761
|
+
this.v4AccessToken = null;
|
|
762
|
+
this.v4AccessTokenExpiresAt = null;
|
|
763
|
+
return {
|
|
764
|
+
ok: false,
|
|
765
|
+
error: {
|
|
766
|
+
name: "SessionExpiredError",
|
|
767
|
+
message: "Session expired."
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
}
|
|
704
772
|
this.refreshing = true;
|
|
705
|
-
const res = await this.authService.refreshSession(
|
|
773
|
+
const res = await this.authService.refreshSession(refreshToken, 4);
|
|
706
774
|
this.refreshing = false;
|
|
707
775
|
if (!res.ok) {
|
|
708
776
|
this.logger.error(`Failed to refresh session: ${res.error.message}`);
|
|
709
777
|
if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
|
|
710
778
|
this.v4AccessToken = null;
|
|
711
779
|
this.v4AccessTokenExpiresAt = null;
|
|
780
|
+
await this.refreshTokenStore.remove();
|
|
712
781
|
}
|
|
713
782
|
return {
|
|
714
783
|
ok: false,
|
|
@@ -716,6 +785,9 @@ var SessionManager = class {
|
|
|
716
785
|
};
|
|
717
786
|
}
|
|
718
787
|
this.logger.success("Session refreshed!");
|
|
788
|
+
if (res.data.refreshToken) {
|
|
789
|
+
await this.refreshTokenStore.set(res.data.refreshToken);
|
|
790
|
+
}
|
|
719
791
|
const now = /* @__PURE__ */ new Date();
|
|
720
792
|
this.v4AccessToken = res.data.accessToken;
|
|
721
793
|
this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
|
|
@@ -748,6 +820,7 @@ var SessionManager = class {
|
|
|
748
820
|
}
|
|
749
821
|
this.v4AccessToken = null;
|
|
750
822
|
this.v4AccessTokenExpiresAt = null;
|
|
823
|
+
await this.refreshTokenStore.remove();
|
|
751
824
|
localStorage.removeItem(this.storageKey);
|
|
752
825
|
}
|
|
753
826
|
async verify() {
|
|
@@ -791,6 +864,7 @@ var SessionManager = class {
|
|
|
791
864
|
localStorage.removeItem(this.storageKey);
|
|
792
865
|
this.v4AccessToken = null;
|
|
793
866
|
this.v4AccessTokenExpiresAt = null;
|
|
867
|
+
await this.refreshTokenStore.remove();
|
|
794
868
|
}
|
|
795
869
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
796
870
|
}
|
|
@@ -820,16 +894,19 @@ var SessionManagerCookie = class {
|
|
|
820
894
|
walletService;
|
|
821
895
|
_refreshing = false;
|
|
822
896
|
/*
|
|
823
|
-
* v4 access tokens
|
|
824
|
-
*
|
|
825
|
-
*
|
|
897
|
+
* v4 access tokens live in memory only, so an XSS-readable storage layer
|
|
898
|
+
* never holds a live one. Re-minted from the HttpOnly cookie, or from
|
|
899
|
+
* `refreshTokenStore` on iOS.
|
|
826
900
|
*/
|
|
827
901
|
v4AccessToken = null;
|
|
828
902
|
v4AccessTokenExpiresAt = null;
|
|
903
|
+
v4RefreshPromise = null;
|
|
904
|
+
refreshTokenStore;
|
|
829
905
|
constructor(config) {
|
|
830
906
|
this.authService = config.authService;
|
|
831
907
|
this.walletService = config.walletService;
|
|
832
908
|
this.logger = config.logger;
|
|
909
|
+
this.refreshTokenStore = createRefreshTokenStore(config.logger);
|
|
833
910
|
}
|
|
834
911
|
get refreshing() {
|
|
835
912
|
return this._refreshing;
|
|
@@ -837,15 +914,18 @@ var SessionManagerCookie = class {
|
|
|
837
914
|
set refreshing(value) {
|
|
838
915
|
this._refreshing = value;
|
|
839
916
|
}
|
|
840
|
-
persist(data, version) {
|
|
917
|
+
async persist(data, version) {
|
|
841
918
|
const now = /* @__PURE__ */ new Date();
|
|
842
919
|
if (version === 4) {
|
|
843
920
|
this.v4AccessToken = data.accessToken ?? null;
|
|
844
921
|
this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
|
|
922
|
+
if (data.refreshToken) {
|
|
923
|
+
await this.refreshTokenStore.set(data.refreshToken);
|
|
924
|
+
}
|
|
845
925
|
cookies.set(
|
|
846
926
|
this.storageKey,
|
|
847
927
|
JSON.stringify({ version, session: data.session }),
|
|
848
|
-
{ expires: subMinutes(addDays(now, 15), 2)
|
|
928
|
+
{ expires: subMinutes(addDays(now, 15), 2) }
|
|
849
929
|
);
|
|
850
930
|
return;
|
|
851
931
|
}
|
|
@@ -857,7 +937,7 @@ var SessionManagerCookie = class {
|
|
|
857
937
|
accessTokenExpiresAt: addMinutes(now, 8).getTime(),
|
|
858
938
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
859
939
|
}),
|
|
860
|
-
{ expires: subMinutes(addDays(now, 30), 2)
|
|
940
|
+
{ expires: subMinutes(addDays(now, 30), 2) }
|
|
861
941
|
);
|
|
862
942
|
}
|
|
863
943
|
async create(input, version = 1) {
|
|
@@ -886,7 +966,7 @@ var SessionManagerCookie = class {
|
|
|
886
966
|
maxAttempt: 5
|
|
887
967
|
})();
|
|
888
968
|
if (!r1.ok) return r1;
|
|
889
|
-
this.persist(r1.data, version);
|
|
969
|
+
await this.persist(r1.data, version);
|
|
890
970
|
return {
|
|
891
971
|
ok: true,
|
|
892
972
|
data: null
|
|
@@ -895,7 +975,7 @@ var SessionManagerCookie = class {
|
|
|
895
975
|
if (input.type === "MOBILE_NUMBER") {
|
|
896
976
|
const res2 = await this.authService.createSession(input, version);
|
|
897
977
|
if (res2.ok) {
|
|
898
|
-
this.persist(res2.data, version);
|
|
978
|
+
await this.persist(res2.data, version);
|
|
899
979
|
return {
|
|
900
980
|
ok: true,
|
|
901
981
|
data: null
|
|
@@ -912,7 +992,7 @@ var SessionManagerCookie = class {
|
|
|
912
992
|
version
|
|
913
993
|
);
|
|
914
994
|
if (res2.ok) {
|
|
915
|
-
this.persist(res2.data, version);
|
|
995
|
+
await this.persist(res2.data, version);
|
|
916
996
|
return {
|
|
917
997
|
ok: true,
|
|
918
998
|
data: null
|
|
@@ -924,7 +1004,7 @@ var SessionManagerCookie = class {
|
|
|
924
1004
|
localStorage.setItem(this.platformStorageKey, "CABINET");
|
|
925
1005
|
const res2 = await this.authService.createSession(input, version);
|
|
926
1006
|
if (res2.ok) {
|
|
927
|
-
this.persist(res2.data, version);
|
|
1007
|
+
await this.persist(res2.data, version);
|
|
928
1008
|
return {
|
|
929
1009
|
ok: true,
|
|
930
1010
|
data: null
|
|
@@ -942,7 +1022,7 @@ var SessionManagerCookie = class {
|
|
|
942
1022
|
}
|
|
943
1023
|
};
|
|
944
1024
|
}
|
|
945
|
-
this.persist(res.data, version);
|
|
1025
|
+
await this.persist(res.data, version);
|
|
946
1026
|
return {
|
|
947
1027
|
ok: true,
|
|
948
1028
|
data: null
|
|
@@ -954,7 +1034,7 @@ var SessionManagerCookie = class {
|
|
|
954
1034
|
if (this.isServer) {
|
|
955
1035
|
this.logger.warn("'client cookies' is not available on the server.");
|
|
956
1036
|
} else {
|
|
957
|
-
this.persist(res.data, 1);
|
|
1037
|
+
await this.persist(res.data, 1);
|
|
958
1038
|
}
|
|
959
1039
|
return { ok: true };
|
|
960
1040
|
} else {
|
|
@@ -1034,7 +1114,7 @@ var SessionManagerCookie = class {
|
|
|
1034
1114
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
1035
1115
|
};
|
|
1036
1116
|
cookies.set(this.storageKey, JSON.stringify(obj), {
|
|
1037
|
-
expires: subMinutes(addDays(now, 30), 2)
|
|
1117
|
+
expires: subMinutes(addDays(now, 30), 2)
|
|
1038
1118
|
});
|
|
1039
1119
|
}
|
|
1040
1120
|
return {
|
|
@@ -1106,7 +1186,7 @@ var SessionManagerCookie = class {
|
|
|
1106
1186
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
1107
1187
|
};
|
|
1108
1188
|
cookies.set(this.storageKey, JSON.stringify(obj), {
|
|
1109
|
-
expires: subMinutes(addDays(now, 30), 2)
|
|
1189
|
+
expires: subMinutes(addDays(now, 30), 2)
|
|
1110
1190
|
});
|
|
1111
1191
|
return {
|
|
1112
1192
|
ok: true,
|
|
@@ -1137,15 +1217,41 @@ var SessionManagerCookie = class {
|
|
|
1137
1217
|
return await this.refreshV4(session);
|
|
1138
1218
|
}
|
|
1139
1219
|
async refreshV4(session) {
|
|
1220
|
+
if (this.v4RefreshPromise) return await this.v4RefreshPromise;
|
|
1221
|
+
this.v4RefreshPromise = this.requestV4Refresh(session);
|
|
1222
|
+
try {
|
|
1223
|
+
return await this.v4RefreshPromise;
|
|
1224
|
+
} finally {
|
|
1225
|
+
this.v4RefreshPromise = null;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
async requestV4Refresh(session) {
|
|
1140
1229
|
this.logger.info("Refreshing session...");
|
|
1230
|
+
let refreshToken;
|
|
1231
|
+
if (isIOSPlatform()) {
|
|
1232
|
+
refreshToken = await this.refreshTokenStore.get() ?? void 0;
|
|
1233
|
+
if (!refreshToken) {
|
|
1234
|
+
this.logger.warn("No stored refresh token. Session expired.");
|
|
1235
|
+
this.v4AccessToken = null;
|
|
1236
|
+
this.v4AccessTokenExpiresAt = null;
|
|
1237
|
+
return {
|
|
1238
|
+
ok: false,
|
|
1239
|
+
error: {
|
|
1240
|
+
name: "SessionExpiredError",
|
|
1241
|
+
message: "Session expired."
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1141
1246
|
this.refreshing = true;
|
|
1142
|
-
const res = await this.authService.refreshSession(
|
|
1247
|
+
const res = await this.authService.refreshSession(refreshToken, 4);
|
|
1143
1248
|
this.refreshing = false;
|
|
1144
1249
|
if (!res.ok) {
|
|
1145
1250
|
this.logger.error(`Failed to refresh session: ${res.error.message}`);
|
|
1146
1251
|
if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
|
|
1147
1252
|
this.v4AccessToken = null;
|
|
1148
1253
|
this.v4AccessTokenExpiresAt = null;
|
|
1254
|
+
await this.refreshTokenStore.remove();
|
|
1149
1255
|
}
|
|
1150
1256
|
return {
|
|
1151
1257
|
ok: false,
|
|
@@ -1153,6 +1259,9 @@ var SessionManagerCookie = class {
|
|
|
1153
1259
|
};
|
|
1154
1260
|
}
|
|
1155
1261
|
this.logger.success("Session refreshed!");
|
|
1262
|
+
if (res.data.refreshToken) {
|
|
1263
|
+
await this.refreshTokenStore.set(res.data.refreshToken);
|
|
1264
|
+
}
|
|
1156
1265
|
const now = /* @__PURE__ */ new Date();
|
|
1157
1266
|
this.v4AccessToken = res.data.accessToken;
|
|
1158
1267
|
this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
|
|
@@ -1185,6 +1294,7 @@ var SessionManagerCookie = class {
|
|
|
1185
1294
|
}
|
|
1186
1295
|
this.v4AccessToken = null;
|
|
1187
1296
|
this.v4AccessTokenExpiresAt = null;
|
|
1297
|
+
await this.refreshTokenStore.remove();
|
|
1188
1298
|
cookies.remove(this.storageKey);
|
|
1189
1299
|
}
|
|
1190
1300
|
async verify() {
|
|
@@ -1228,6 +1338,7 @@ var SessionManagerCookie = class {
|
|
|
1228
1338
|
cookies.remove(this.storageKey);
|
|
1229
1339
|
this.v4AccessToken = null;
|
|
1230
1340
|
this.v4AccessTokenExpiresAt = null;
|
|
1341
|
+
await this.refreshTokenStore.remove();
|
|
1231
1342
|
}
|
|
1232
1343
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
1233
1344
|
}
|