@opexa/portal-sdk 0.59.95 → 0.59.97
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 +254 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +223 -72
- 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,23 @@ 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
|
+
invalidReason = null;
|
|
398
|
+
refreshTokenStore;
|
|
355
399
|
constructor(config) {
|
|
356
400
|
this.authService = config.authService;
|
|
357
401
|
this.walletService = config.walletService;
|
|
358
402
|
this.logger = config.logger;
|
|
403
|
+
this.refreshTokenStore = createRefreshTokenStore(
|
|
404
|
+
config.logger,
|
|
405
|
+
config.sessionPrefix
|
|
406
|
+
);
|
|
359
407
|
if (config.sessionPrefix) {
|
|
360
408
|
this.storageKey = `${config.sessionPrefix}/${this.storageKey}`;
|
|
361
409
|
this.platformStorageKey = `${config.sessionPrefix}/${this.platformStorageKey}`;
|
|
@@ -367,7 +415,7 @@ var SessionManager = class {
|
|
|
367
415
|
set refreshing(value) {
|
|
368
416
|
this._refreshing = value;
|
|
369
417
|
}
|
|
370
|
-
persist(data, version) {
|
|
418
|
+
async persist(data, version) {
|
|
371
419
|
const now = /* @__PURE__ */ new Date();
|
|
372
420
|
if (version === 4) {
|
|
373
421
|
if (!data.session || !data.accessToken) {
|
|
@@ -378,12 +426,17 @@ var SessionManager = class {
|
|
|
378
426
|
}
|
|
379
427
|
this.v4AccessToken = data.accessToken;
|
|
380
428
|
this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
|
|
429
|
+
this.invalidReason = null;
|
|
430
|
+
if (data.refreshToken) {
|
|
431
|
+
await this.refreshTokenStore.set(data.refreshToken);
|
|
432
|
+
}
|
|
381
433
|
localStorage.setItem(
|
|
382
434
|
this.storageKey,
|
|
383
435
|
JSON.stringify({ version, session: data.session })
|
|
384
436
|
);
|
|
385
437
|
return true;
|
|
386
438
|
}
|
|
439
|
+
this.invalidReason = null;
|
|
387
440
|
localStorage.setItem(
|
|
388
441
|
this.storageKey,
|
|
389
442
|
JSON.stringify({
|
|
@@ -440,7 +493,8 @@ var SessionManager = class {
|
|
|
440
493
|
maxAttempt: 5
|
|
441
494
|
})();
|
|
442
495
|
if (!r1.ok) return r1;
|
|
443
|
-
if (!this.persist(r1.data, version))
|
|
496
|
+
if (!await this.persist(r1.data, version))
|
|
497
|
+
return this.malformedResponseError();
|
|
444
498
|
return {
|
|
445
499
|
ok: true,
|
|
446
500
|
data: null
|
|
@@ -449,7 +503,7 @@ var SessionManager = class {
|
|
|
449
503
|
if (input.type === "MOBILE_NUMBER") {
|
|
450
504
|
const res2 = await this.authService.createSession(input, version);
|
|
451
505
|
if (res2.ok) {
|
|
452
|
-
if (!this.persist(res2.data, version))
|
|
506
|
+
if (!await this.persist(res2.data, version))
|
|
453
507
|
return this.malformedResponseError();
|
|
454
508
|
return {
|
|
455
509
|
ok: true,
|
|
@@ -468,7 +522,7 @@ var SessionManager = class {
|
|
|
468
522
|
version
|
|
469
523
|
);
|
|
470
524
|
if (res2.ok) {
|
|
471
|
-
if (!this.persist(res2.data, version))
|
|
525
|
+
if (!await this.persist(res2.data, version))
|
|
472
526
|
return this.malformedResponseError();
|
|
473
527
|
return {
|
|
474
528
|
ok: true,
|
|
@@ -481,7 +535,7 @@ var SessionManager = class {
|
|
|
481
535
|
localStorage.setItem(this.platformStorageKey, "CABINET");
|
|
482
536
|
const res2 = await this.authService.createSession(input, version);
|
|
483
537
|
if (res2.ok) {
|
|
484
|
-
if (!this.persist(res2.data, version))
|
|
538
|
+
if (!await this.persist(res2.data, version))
|
|
485
539
|
return this.malformedResponseError();
|
|
486
540
|
return {
|
|
487
541
|
ok: true,
|
|
@@ -500,7 +554,8 @@ var SessionManager = class {
|
|
|
500
554
|
}
|
|
501
555
|
};
|
|
502
556
|
}
|
|
503
|
-
if (!this.persist(res.data, version))
|
|
557
|
+
if (!await this.persist(res.data, version))
|
|
558
|
+
return this.malformedResponseError();
|
|
504
559
|
return {
|
|
505
560
|
ok: true,
|
|
506
561
|
data: null
|
|
@@ -511,7 +566,7 @@ var SessionManager = class {
|
|
|
511
566
|
if (res.ok) {
|
|
512
567
|
if (this.isServer) {
|
|
513
568
|
this.logger.warn("'localStorage' is not available on the server.");
|
|
514
|
-
} else if (!this.persist(res.data, 1)) {
|
|
569
|
+
} else if (!await this.persist(res.data, 1)) {
|
|
515
570
|
return this.malformedResponseError();
|
|
516
571
|
}
|
|
517
572
|
return { ok: true };
|
|
@@ -607,6 +662,20 @@ var SessionManager = class {
|
|
|
607
662
|
};
|
|
608
663
|
}
|
|
609
664
|
}
|
|
665
|
+
async getV4(session) {
|
|
666
|
+
const now = /* @__PURE__ */ new Date();
|
|
667
|
+
if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
|
|
668
|
+
return {
|
|
669
|
+
ok: true,
|
|
670
|
+
data: {
|
|
671
|
+
session,
|
|
672
|
+
accessToken: this.v4AccessToken,
|
|
673
|
+
accessTokenExpiresAt: this.v4AccessTokenExpiresAt
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
return await this.refreshV4(session);
|
|
678
|
+
}
|
|
610
679
|
async refresh() {
|
|
611
680
|
if (this.isServer) {
|
|
612
681
|
this.logger.warn("'localStorage' is not available on the server.");
|
|
@@ -676,20 +745,6 @@ var SessionManager = class {
|
|
|
676
745
|
};
|
|
677
746
|
}
|
|
678
747
|
}
|
|
679
|
-
async getV4(session) {
|
|
680
|
-
const now = /* @__PURE__ */ new Date();
|
|
681
|
-
if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
|
|
682
|
-
return {
|
|
683
|
-
ok: true,
|
|
684
|
-
data: {
|
|
685
|
-
session,
|
|
686
|
-
accessToken: this.v4AccessToken,
|
|
687
|
-
accessTokenExpiresAt: this.v4AccessTokenExpiresAt
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
return await this.refreshV4(session);
|
|
692
|
-
}
|
|
693
748
|
async refreshV4(session) {
|
|
694
749
|
if (this.v4RefreshPromise) return await this.v4RefreshPromise;
|
|
695
750
|
this.v4RefreshPromise = this.requestV4Refresh(session);
|
|
@@ -701,21 +756,48 @@ var SessionManager = class {
|
|
|
701
756
|
}
|
|
702
757
|
async requestV4Refresh(session) {
|
|
703
758
|
this.logger.info("Refreshing session...");
|
|
759
|
+
let refreshToken;
|
|
760
|
+
if (isIOSPlatform()) {
|
|
761
|
+
refreshToken = await this.refreshTokenStore.get() ?? void 0;
|
|
762
|
+
if (!refreshToken) {
|
|
763
|
+
this.logger.warn("No stored refresh token. Session expired.");
|
|
764
|
+
this.v4AccessToken = null;
|
|
765
|
+
this.v4AccessTokenExpiresAt = null;
|
|
766
|
+
this.invalidReason = "REFRESH_TOKEN_EXPIRED";
|
|
767
|
+
localStorage.removeItem(this.storageKey);
|
|
768
|
+
return {
|
|
769
|
+
ok: false,
|
|
770
|
+
error: {
|
|
771
|
+
name: "SessionExpiredError",
|
|
772
|
+
message: "Session expired."
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
}
|
|
704
777
|
this.refreshing = true;
|
|
705
|
-
const res = await this.authService.refreshSession(
|
|
706
|
-
this.refreshing = false;
|
|
778
|
+
const res = await this.authService.refreshSession(refreshToken, 4);
|
|
707
779
|
if (!res.ok) {
|
|
708
780
|
this.logger.error(`Failed to refresh session: ${res.error.message}`);
|
|
709
|
-
|
|
781
|
+
const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
|
|
782
|
+
if (terminal) {
|
|
710
783
|
this.v4AccessToken = null;
|
|
711
784
|
this.v4AccessTokenExpiresAt = null;
|
|
785
|
+
this.invalidReason = res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION";
|
|
786
|
+
localStorage.removeItem(this.storageKey);
|
|
712
787
|
}
|
|
788
|
+
this.refreshing = false;
|
|
789
|
+
if (terminal) await this.refreshTokenStore.remove();
|
|
713
790
|
return {
|
|
714
791
|
ok: false,
|
|
715
792
|
error: res.error
|
|
716
793
|
};
|
|
717
794
|
}
|
|
795
|
+
this.refreshing = false;
|
|
718
796
|
this.logger.success("Session refreshed!");
|
|
797
|
+
this.invalidReason = null;
|
|
798
|
+
if (res.data.refreshToken) {
|
|
799
|
+
await this.refreshTokenStore.set(res.data.refreshToken);
|
|
800
|
+
}
|
|
719
801
|
const now = /* @__PURE__ */ new Date();
|
|
720
802
|
this.v4AccessToken = res.data.accessToken;
|
|
721
803
|
this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
|
|
@@ -748,6 +830,8 @@ var SessionManager = class {
|
|
|
748
830
|
}
|
|
749
831
|
this.v4AccessToken = null;
|
|
750
832
|
this.v4AccessTokenExpiresAt = null;
|
|
833
|
+
this.invalidReason = null;
|
|
834
|
+
await this.refreshTokenStore.remove();
|
|
751
835
|
localStorage.removeItem(this.storageKey);
|
|
752
836
|
}
|
|
753
837
|
async verify() {
|
|
@@ -755,6 +839,9 @@ var SessionManager = class {
|
|
|
755
839
|
this.logger.warn("'localStorage' is not available on the server.");
|
|
756
840
|
return { valid: true };
|
|
757
841
|
}
|
|
842
|
+
if (this.invalidReason) {
|
|
843
|
+
return { valid: false, reason: this.invalidReason };
|
|
844
|
+
}
|
|
758
845
|
const val = localStorage.getItem(this.storageKey);
|
|
759
846
|
if (val) {
|
|
760
847
|
try {
|
|
@@ -769,11 +856,13 @@ var SessionManager = class {
|
|
|
769
856
|
}
|
|
770
857
|
const s = await this.get();
|
|
771
858
|
if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
|
|
859
|
+
this.invalidReason = "INVALID_SESSION";
|
|
772
860
|
return { valid: false, reason: "INVALID_SESSION" };
|
|
773
861
|
}
|
|
774
862
|
if (!s.data) return { valid: true };
|
|
775
863
|
const v = await this.authService.verifySession(s.data.accessToken);
|
|
776
864
|
if (!v) {
|
|
865
|
+
this.invalidReason = "INVALID_SESSION";
|
|
777
866
|
localStorage.removeItem(this.storageKey);
|
|
778
867
|
}
|
|
779
868
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
@@ -781,16 +870,17 @@ var SessionManager = class {
|
|
|
781
870
|
async verifyV4(session) {
|
|
782
871
|
if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
|
|
783
872
|
const res = await this.refreshV4(session);
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
};
|
|
873
|
+
if (res.ok) return { valid: true };
|
|
874
|
+
if (!this.invalidReason) return { valid: true };
|
|
875
|
+
return { valid: false, reason: this.invalidReason };
|
|
788
876
|
}
|
|
789
877
|
const v = await this.authService.verifySession(this.v4AccessToken);
|
|
790
878
|
if (!v) {
|
|
791
879
|
localStorage.removeItem(this.storageKey);
|
|
792
880
|
this.v4AccessToken = null;
|
|
793
881
|
this.v4AccessTokenExpiresAt = null;
|
|
882
|
+
this.invalidReason = "INVALID_SESSION";
|
|
883
|
+
await this.refreshTokenStore.remove();
|
|
794
884
|
}
|
|
795
885
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
796
886
|
}
|
|
@@ -820,16 +910,20 @@ var SessionManagerCookie = class {
|
|
|
820
910
|
walletService;
|
|
821
911
|
_refreshing = false;
|
|
822
912
|
/*
|
|
823
|
-
* v4 access tokens
|
|
824
|
-
*
|
|
825
|
-
*
|
|
913
|
+
* v4 access tokens live in memory only, so an XSS-readable storage layer
|
|
914
|
+
* never holds a live one. Re-minted from the HttpOnly cookie, or from
|
|
915
|
+
* `refreshTokenStore` on iOS.
|
|
826
916
|
*/
|
|
827
917
|
v4AccessToken = null;
|
|
828
918
|
v4AccessTokenExpiresAt = null;
|
|
919
|
+
v4RefreshPromise = null;
|
|
920
|
+
invalidReason = null;
|
|
921
|
+
refreshTokenStore;
|
|
829
922
|
constructor(config) {
|
|
830
923
|
this.authService = config.authService;
|
|
831
924
|
this.walletService = config.walletService;
|
|
832
925
|
this.logger = config.logger;
|
|
926
|
+
this.refreshTokenStore = createRefreshTokenStore(config.logger);
|
|
833
927
|
}
|
|
834
928
|
get refreshing() {
|
|
835
929
|
return this._refreshing;
|
|
@@ -837,15 +931,19 @@ var SessionManagerCookie = class {
|
|
|
837
931
|
set refreshing(value) {
|
|
838
932
|
this._refreshing = value;
|
|
839
933
|
}
|
|
840
|
-
persist(data, version) {
|
|
934
|
+
async persist(data, version) {
|
|
841
935
|
const now = /* @__PURE__ */ new Date();
|
|
936
|
+
this.invalidReason = null;
|
|
842
937
|
if (version === 4) {
|
|
843
938
|
this.v4AccessToken = data.accessToken ?? null;
|
|
844
939
|
this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
|
|
940
|
+
if (data.refreshToken) {
|
|
941
|
+
await this.refreshTokenStore.set(data.refreshToken);
|
|
942
|
+
}
|
|
845
943
|
cookies.set(
|
|
846
944
|
this.storageKey,
|
|
847
945
|
JSON.stringify({ version, session: data.session }),
|
|
848
|
-
{ expires: subMinutes(addDays(now, 15), 2)
|
|
946
|
+
{ expires: subMinutes(addDays(now, 15), 2) }
|
|
849
947
|
);
|
|
850
948
|
return;
|
|
851
949
|
}
|
|
@@ -857,7 +955,7 @@ var SessionManagerCookie = class {
|
|
|
857
955
|
accessTokenExpiresAt: addMinutes(now, 8).getTime(),
|
|
858
956
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
859
957
|
}),
|
|
860
|
-
{ expires: subMinutes(addDays(now, 30), 2)
|
|
958
|
+
{ expires: subMinutes(addDays(now, 30), 2) }
|
|
861
959
|
);
|
|
862
960
|
}
|
|
863
961
|
async create(input, version = 1) {
|
|
@@ -886,7 +984,7 @@ var SessionManagerCookie = class {
|
|
|
886
984
|
maxAttempt: 5
|
|
887
985
|
})();
|
|
888
986
|
if (!r1.ok) return r1;
|
|
889
|
-
this.persist(r1.data, version);
|
|
987
|
+
await this.persist(r1.data, version);
|
|
890
988
|
return {
|
|
891
989
|
ok: true,
|
|
892
990
|
data: null
|
|
@@ -895,7 +993,7 @@ var SessionManagerCookie = class {
|
|
|
895
993
|
if (input.type === "MOBILE_NUMBER") {
|
|
896
994
|
const res2 = await this.authService.createSession(input, version);
|
|
897
995
|
if (res2.ok) {
|
|
898
|
-
this.persist(res2.data, version);
|
|
996
|
+
await this.persist(res2.data, version);
|
|
899
997
|
return {
|
|
900
998
|
ok: true,
|
|
901
999
|
data: null
|
|
@@ -912,7 +1010,7 @@ var SessionManagerCookie = class {
|
|
|
912
1010
|
version
|
|
913
1011
|
);
|
|
914
1012
|
if (res2.ok) {
|
|
915
|
-
this.persist(res2.data, version);
|
|
1013
|
+
await this.persist(res2.data, version);
|
|
916
1014
|
return {
|
|
917
1015
|
ok: true,
|
|
918
1016
|
data: null
|
|
@@ -924,7 +1022,7 @@ var SessionManagerCookie = class {
|
|
|
924
1022
|
localStorage.setItem(this.platformStorageKey, "CABINET");
|
|
925
1023
|
const res2 = await this.authService.createSession(input, version);
|
|
926
1024
|
if (res2.ok) {
|
|
927
|
-
this.persist(res2.data, version);
|
|
1025
|
+
await this.persist(res2.data, version);
|
|
928
1026
|
return {
|
|
929
1027
|
ok: true,
|
|
930
1028
|
data: null
|
|
@@ -942,7 +1040,7 @@ var SessionManagerCookie = class {
|
|
|
942
1040
|
}
|
|
943
1041
|
};
|
|
944
1042
|
}
|
|
945
|
-
this.persist(res.data, version);
|
|
1043
|
+
await this.persist(res.data, version);
|
|
946
1044
|
return {
|
|
947
1045
|
ok: true,
|
|
948
1046
|
data: null
|
|
@@ -954,7 +1052,7 @@ var SessionManagerCookie = class {
|
|
|
954
1052
|
if (this.isServer) {
|
|
955
1053
|
this.logger.warn("'client cookies' is not available on the server.");
|
|
956
1054
|
} else {
|
|
957
|
-
this.persist(res.data, 1);
|
|
1055
|
+
await this.persist(res.data, 1);
|
|
958
1056
|
}
|
|
959
1057
|
return { ok: true };
|
|
960
1058
|
} else {
|
|
@@ -1034,7 +1132,7 @@ var SessionManagerCookie = class {
|
|
|
1034
1132
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
1035
1133
|
};
|
|
1036
1134
|
cookies.set(this.storageKey, JSON.stringify(obj), {
|
|
1037
|
-
expires: subMinutes(addDays(now, 30), 2)
|
|
1135
|
+
expires: subMinutes(addDays(now, 30), 2)
|
|
1038
1136
|
});
|
|
1039
1137
|
}
|
|
1040
1138
|
return {
|
|
@@ -1051,6 +1149,20 @@ var SessionManagerCookie = class {
|
|
|
1051
1149
|
};
|
|
1052
1150
|
}
|
|
1053
1151
|
}
|
|
1152
|
+
async getV4(session) {
|
|
1153
|
+
const now = /* @__PURE__ */ new Date();
|
|
1154
|
+
if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
|
|
1155
|
+
return {
|
|
1156
|
+
ok: true,
|
|
1157
|
+
data: {
|
|
1158
|
+
session,
|
|
1159
|
+
accessToken: this.v4AccessToken,
|
|
1160
|
+
accessTokenExpiresAt: this.v4AccessTokenExpiresAt
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
return await this.refreshV4(session);
|
|
1165
|
+
}
|
|
1054
1166
|
async refresh() {
|
|
1055
1167
|
if (this.isServer) {
|
|
1056
1168
|
this.logger.warn("'client cookies' is not available on the server.");
|
|
@@ -1106,7 +1218,7 @@ var SessionManagerCookie = class {
|
|
|
1106
1218
|
refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
|
|
1107
1219
|
};
|
|
1108
1220
|
cookies.set(this.storageKey, JSON.stringify(obj), {
|
|
1109
|
-
expires: subMinutes(addDays(now, 30), 2)
|
|
1221
|
+
expires: subMinutes(addDays(now, 30), 2)
|
|
1110
1222
|
});
|
|
1111
1223
|
return {
|
|
1112
1224
|
ok: true,
|
|
@@ -1122,37 +1234,59 @@ var SessionManagerCookie = class {
|
|
|
1122
1234
|
};
|
|
1123
1235
|
}
|
|
1124
1236
|
}
|
|
1125
|
-
async
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
accessToken: this.v4AccessToken,
|
|
1133
|
-
accessTokenExpiresAt: this.v4AccessTokenExpiresAt
|
|
1134
|
-
}
|
|
1135
|
-
};
|
|
1237
|
+
async refreshV4(session) {
|
|
1238
|
+
if (this.v4RefreshPromise) return await this.v4RefreshPromise;
|
|
1239
|
+
this.v4RefreshPromise = this.requestV4Refresh(session);
|
|
1240
|
+
try {
|
|
1241
|
+
return await this.v4RefreshPromise;
|
|
1242
|
+
} finally {
|
|
1243
|
+
this.v4RefreshPromise = null;
|
|
1136
1244
|
}
|
|
1137
|
-
return await this.refreshV4(session);
|
|
1138
1245
|
}
|
|
1139
|
-
async
|
|
1246
|
+
async requestV4Refresh(session) {
|
|
1140
1247
|
this.logger.info("Refreshing session...");
|
|
1248
|
+
let refreshToken;
|
|
1249
|
+
if (isIOSPlatform()) {
|
|
1250
|
+
refreshToken = await this.refreshTokenStore.get() ?? void 0;
|
|
1251
|
+
if (!refreshToken) {
|
|
1252
|
+
this.logger.warn("No stored refresh token. Session expired.");
|
|
1253
|
+
this.v4AccessToken = null;
|
|
1254
|
+
this.v4AccessTokenExpiresAt = null;
|
|
1255
|
+
this.invalidReason = "REFRESH_TOKEN_EXPIRED";
|
|
1256
|
+
cookies.remove(this.storageKey);
|
|
1257
|
+
return {
|
|
1258
|
+
ok: false,
|
|
1259
|
+
error: {
|
|
1260
|
+
name: "SessionExpiredError",
|
|
1261
|
+
message: "Session expired."
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1141
1266
|
this.refreshing = true;
|
|
1142
|
-
const res = await this.authService.refreshSession(
|
|
1143
|
-
this.refreshing = false;
|
|
1267
|
+
const res = await this.authService.refreshSession(refreshToken, 4);
|
|
1144
1268
|
if (!res.ok) {
|
|
1145
1269
|
this.logger.error(`Failed to refresh session: ${res.error.message}`);
|
|
1146
|
-
|
|
1270
|
+
const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
|
|
1271
|
+
if (terminal) {
|
|
1147
1272
|
this.v4AccessToken = null;
|
|
1148
1273
|
this.v4AccessTokenExpiresAt = null;
|
|
1274
|
+
this.invalidReason = res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION";
|
|
1275
|
+
cookies.remove(this.storageKey);
|
|
1149
1276
|
}
|
|
1277
|
+
this.refreshing = false;
|
|
1278
|
+
if (terminal) await this.refreshTokenStore.remove();
|
|
1150
1279
|
return {
|
|
1151
1280
|
ok: false,
|
|
1152
1281
|
error: res.error
|
|
1153
1282
|
};
|
|
1154
1283
|
}
|
|
1284
|
+
this.refreshing = false;
|
|
1155
1285
|
this.logger.success("Session refreshed!");
|
|
1286
|
+
this.invalidReason = null;
|
|
1287
|
+
if (res.data.refreshToken) {
|
|
1288
|
+
await this.refreshTokenStore.set(res.data.refreshToken);
|
|
1289
|
+
}
|
|
1156
1290
|
const now = /* @__PURE__ */ new Date();
|
|
1157
1291
|
this.v4AccessToken = res.data.accessToken;
|
|
1158
1292
|
this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
|
|
@@ -1185,6 +1319,8 @@ var SessionManagerCookie = class {
|
|
|
1185
1319
|
}
|
|
1186
1320
|
this.v4AccessToken = null;
|
|
1187
1321
|
this.v4AccessTokenExpiresAt = null;
|
|
1322
|
+
this.invalidReason = null;
|
|
1323
|
+
await this.refreshTokenStore.remove();
|
|
1188
1324
|
cookies.remove(this.storageKey);
|
|
1189
1325
|
}
|
|
1190
1326
|
async verify() {
|
|
@@ -1192,6 +1328,9 @@ var SessionManagerCookie = class {
|
|
|
1192
1328
|
this.logger.warn("'client cookies' is not available on the server.");
|
|
1193
1329
|
return { valid: true };
|
|
1194
1330
|
}
|
|
1331
|
+
if (this.invalidReason) {
|
|
1332
|
+
return { valid: false, reason: this.invalidReason };
|
|
1333
|
+
}
|
|
1195
1334
|
const val = cookies.get(this.storageKey);
|
|
1196
1335
|
if (val) {
|
|
1197
1336
|
try {
|
|
@@ -1206,11 +1345,13 @@ var SessionManagerCookie = class {
|
|
|
1206
1345
|
}
|
|
1207
1346
|
const s = await this.get();
|
|
1208
1347
|
if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
|
|
1348
|
+
this.invalidReason = "INVALID_SESSION";
|
|
1209
1349
|
return { valid: false, reason: "INVALID_SESSION" };
|
|
1210
1350
|
}
|
|
1211
1351
|
if (!s.data) return { valid: true };
|
|
1212
1352
|
const v = await this.authService.verifySession(s.data.accessToken);
|
|
1213
1353
|
if (!v) {
|
|
1354
|
+
this.invalidReason = "INVALID_SESSION";
|
|
1214
1355
|
cookies.remove(this.storageKey);
|
|
1215
1356
|
}
|
|
1216
1357
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
@@ -1218,16 +1359,17 @@ var SessionManagerCookie = class {
|
|
|
1218
1359
|
async verifyV4(session) {
|
|
1219
1360
|
if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
|
|
1220
1361
|
const res = await this.refreshV4(session);
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
};
|
|
1362
|
+
if (res.ok) return { valid: true };
|
|
1363
|
+
if (!this.invalidReason) return { valid: true };
|
|
1364
|
+
return { valid: false, reason: this.invalidReason };
|
|
1225
1365
|
}
|
|
1226
1366
|
const v = await this.authService.verifySession(this.v4AccessToken);
|
|
1227
1367
|
if (!v) {
|
|
1228
1368
|
cookies.remove(this.storageKey);
|
|
1229
1369
|
this.v4AccessToken = null;
|
|
1230
1370
|
this.v4AccessTokenExpiresAt = null;
|
|
1371
|
+
this.invalidReason = "INVALID_SESSION";
|
|
1372
|
+
await this.refreshTokenStore.remove();
|
|
1231
1373
|
}
|
|
1232
1374
|
return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
|
|
1233
1375
|
}
|
|
@@ -3532,9 +3674,18 @@ var Sdk = class {
|
|
|
3532
3674
|
let counter = 0;
|
|
3533
3675
|
let timeout = null;
|
|
3534
3676
|
let isForeground = true;
|
|
3677
|
+
let stopped = false;
|
|
3535
3678
|
const listener = App.addListener("appStateChange", ({ isActive }) => {
|
|
3536
3679
|
isForeground = isActive;
|
|
3537
3680
|
});
|
|
3681
|
+
const stop = () => {
|
|
3682
|
+
stopped = true;
|
|
3683
|
+
if (timeout) {
|
|
3684
|
+
clearTimeout(timeout);
|
|
3685
|
+
timeout = null;
|
|
3686
|
+
}
|
|
3687
|
+
listener.then((handle) => handle.remove());
|
|
3688
|
+
};
|
|
3538
3689
|
const assignTimeout = () => {
|
|
3539
3690
|
const duration = counter <= 0 ? interval * 0.5 : interval;
|
|
3540
3691
|
return setTimeout(async () => {
|
|
@@ -3543,10 +3694,13 @@ var Sdk = class {
|
|
|
3543
3694
|
try {
|
|
3544
3695
|
res = await this.sessionManager.verify();
|
|
3545
3696
|
} catch {
|
|
3546
|
-
res =
|
|
3697
|
+
res = null;
|
|
3547
3698
|
}
|
|
3548
|
-
if (
|
|
3699
|
+
if (stopped) return;
|
|
3700
|
+
if (res && !res.valid) {
|
|
3701
|
+
stop();
|
|
3549
3702
|
await input.onInvalid(res.reason ?? "INVALID_SESSION");
|
|
3703
|
+
return;
|
|
3550
3704
|
}
|
|
3551
3705
|
}
|
|
3552
3706
|
counter += 1;
|
|
@@ -3555,10 +3709,7 @@ var Sdk = class {
|
|
|
3555
3709
|
};
|
|
3556
3710
|
timeout = assignTimeout();
|
|
3557
3711
|
return function unsubscribe() {
|
|
3558
|
-
|
|
3559
|
-
clearTimeout(timeout);
|
|
3560
|
-
}
|
|
3561
|
-
listener.then((handle) => handle.remove());
|
|
3712
|
+
stop();
|
|
3562
3713
|
};
|
|
3563
3714
|
}
|
|
3564
3715
|
async session() {
|