@metamask-previews/seedless-onboarding-controller 2.0.1-preview-c10fdda1 → 2.0.1-preview-32f9004a
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/CHANGELOG.md +0 -6
- package/dist/SeedlessOnboardingController.cjs +17 -120
- package/dist/SeedlessOnboardingController.cjs.map +1 -1
- package/dist/SeedlessOnboardingController.d.cts +3 -19
- package/dist/SeedlessOnboardingController.d.cts.map +1 -1
- package/dist/SeedlessOnboardingController.d.mts +3 -19
- package/dist/SeedlessOnboardingController.d.mts.map +1 -1
- package/dist/SeedlessOnboardingController.mjs +17 -120
- package/dist/SeedlessOnboardingController.mjs.map +1 -1
- package/dist/constants.cjs +0 -2
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +0 -2
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +0 -2
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +0 -2
- package/dist/constants.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +0 -38
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +0 -38
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,12 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Added `access_token` and `metadata_access_token` in seedless controller state. ([#6060](https://github.com/MetaMask/core/pull/6060))
|
|
13
|
-
- `access_token` can be used by profile sync pairing and for other apis access after wallet is unlocked.
|
|
14
|
-
- `metadata_access_token` is used to give access for web3auth metadata apis.
|
|
15
|
-
|
|
16
10
|
## [2.0.1]
|
|
17
11
|
|
|
18
12
|
### Fixed
|
|
@@ -102,17 +102,6 @@ const seedlessOnboardingMetadata = {
|
|
|
102
102
|
persist: false,
|
|
103
103
|
anonymous: true,
|
|
104
104
|
},
|
|
105
|
-
// stays in vault
|
|
106
|
-
accessToken: {
|
|
107
|
-
persist: false,
|
|
108
|
-
anonymous: true,
|
|
109
|
-
},
|
|
110
|
-
// stays outside of vault as this token is accessed by the metadata service
|
|
111
|
-
// before the vault is created or unlocked.
|
|
112
|
-
metadataAccessToken: {
|
|
113
|
-
persist: true,
|
|
114
|
-
anonymous: true,
|
|
115
|
-
},
|
|
116
105
|
encryptedSeedlessEncryptionKey: {
|
|
117
106
|
persist: true,
|
|
118
107
|
anonymous: true,
|
|
@@ -161,7 +150,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
161
150
|
this.toprfClient = new toprf_secure_backup_1.ToprfSecureBackup({
|
|
162
151
|
network,
|
|
163
152
|
keyDeriver: toprfKeyDeriver,
|
|
164
|
-
fetchMetadataAccessCreds: this.fetchMetadataAccessCreds.bind(this),
|
|
165
153
|
});
|
|
166
154
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_refreshJWTToken, refreshJWTToken, "f");
|
|
167
155
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_revokeRefreshToken, revokeRefreshToken, "f");
|
|
@@ -174,25 +162,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
174
162
|
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_setUnlocked).call(this);
|
|
175
163
|
});
|
|
176
164
|
}
|
|
177
|
-
async fetchMetadataAccessCreds() {
|
|
178
|
-
const { metadataAccessToken } = this.state;
|
|
179
|
-
if (!metadataAccessToken) {
|
|
180
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidMetadataAccessToken);
|
|
181
|
-
}
|
|
182
|
-
// Check if token is expired and refresh if needed
|
|
183
|
-
const decodedToken = this.decodeJWTToken(metadataAccessToken);
|
|
184
|
-
if (decodedToken.exp < Math.floor(Date.now() / 1000)) {
|
|
185
|
-
// Token is expired, refresh it
|
|
186
|
-
await this.refreshAuthTokens();
|
|
187
|
-
// Get the new token after refresh
|
|
188
|
-
const { metadataAccessToken: newMetadataAccessToken } = this.state;
|
|
189
|
-
if (!newMetadataAccessToken) {
|
|
190
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidMetadataAccessToken);
|
|
191
|
-
}
|
|
192
|
-
return { metadataAccessToken: newMetadataAccessToken };
|
|
193
|
-
}
|
|
194
|
-
return { metadataAccessToken };
|
|
195
|
-
}
|
|
196
165
|
/**
|
|
197
166
|
* Authenticate OAuth user using the seedless onboarding flow
|
|
198
167
|
* and determine if the user is already registered or not.
|
|
@@ -206,15 +175,13 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
206
175
|
* @param params.socialLoginEmail - The user email from Social login.
|
|
207
176
|
* @param params.refreshToken - refresh token for refreshing expired nodeAuthTokens.
|
|
208
177
|
* @param params.revokeToken - revoke token for revoking refresh token and get new refresh token and new revoke token.
|
|
209
|
-
* @param params.accessToken - Access token for pairing with profile sync auth service and to access other services.
|
|
210
|
-
* @param params.metadataAccessToken - Metadata access token for accessing the metadata service before the vault is created or unlocked.
|
|
211
178
|
* @param params.skipLock - Optional flag to skip acquiring the controller lock. (to prevent deadlock in case the caller already acquired the lock)
|
|
212
179
|
* @returns A promise that resolves to the authentication result.
|
|
213
180
|
*/
|
|
214
181
|
async authenticate(params) {
|
|
215
182
|
const doAuthenticateWithNodes = async () => {
|
|
216
183
|
try {
|
|
217
|
-
const { idTokens, authConnectionId, groupedAuthConnectionId, userId, authConnection, socialLoginEmail, refreshToken, revokeToken,
|
|
184
|
+
const { idTokens, authConnectionId, groupedAuthConnectionId, userId, authConnection, socialLoginEmail, refreshToken, revokeToken, } = params;
|
|
218
185
|
const authenticationResult = await this.toprfClient.authenticate({
|
|
219
186
|
authConnectionId,
|
|
220
187
|
userId,
|
|
@@ -236,12 +203,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
236
203
|
// Temporarily store revoke token in state for later vault creation
|
|
237
204
|
state.revokeToken = revokeToken;
|
|
238
205
|
}
|
|
239
|
-
if (accessToken) {
|
|
240
|
-
state.accessToken = accessToken;
|
|
241
|
-
}
|
|
242
|
-
if (metadataAccessToken) {
|
|
243
|
-
state.metadataAccessToken = metadataAccessToken;
|
|
244
|
-
}
|
|
245
206
|
});
|
|
246
207
|
return authenticationResult;
|
|
247
208
|
}
|
|
@@ -500,7 +461,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
500
461
|
delete state.vaultEncryptionKey;
|
|
501
462
|
delete state.vaultEncryptionSalt;
|
|
502
463
|
delete state.revokeToken;
|
|
503
|
-
delete state.accessToken;
|
|
504
464
|
});
|
|
505
465
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_isUnlocked, false, "f");
|
|
506
466
|
}
|
|
@@ -622,14 +582,14 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
622
582
|
return await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_loadKeyringEncryptionKey).call(this, encKey);
|
|
623
583
|
}
|
|
624
584
|
/**
|
|
625
|
-
* Refresh expired nodeAuthTokens
|
|
585
|
+
* Refresh expired nodeAuthTokens using the stored refresh token.
|
|
626
586
|
*
|
|
627
587
|
* This method retrieves the refresh token from the vault and uses it to obtain
|
|
628
588
|
* new nodeAuthTokens when the current ones have expired.
|
|
629
589
|
*
|
|
630
590
|
* @returns A promise that resolves to the new nodeAuthTokens.
|
|
631
591
|
*/
|
|
632
|
-
async
|
|
592
|
+
async refreshNodeAuthTokens() {
|
|
633
593
|
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
|
|
634
594
|
const { refreshToken } = this.state;
|
|
635
595
|
try {
|
|
@@ -637,12 +597,10 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
637
597
|
connection: this.state.authConnection,
|
|
638
598
|
refreshToken,
|
|
639
599
|
});
|
|
640
|
-
const { idTokens
|
|
600
|
+
const { idTokens } = res;
|
|
641
601
|
// re-authenticate with the new id tokens to set new node auth tokens
|
|
642
602
|
await this.authenticate({
|
|
643
603
|
idTokens,
|
|
644
|
-
accessToken,
|
|
645
|
-
metadataAccessToken,
|
|
646
604
|
authConnection: this.state.authConnection,
|
|
647
605
|
authConnectionId: this.state.authConnectionId,
|
|
648
606
|
groupedAuthConnectionId: this.state.groupedAuthConnectionId,
|
|
@@ -698,34 +656,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
698
656
|
// check if the token is expired
|
|
699
657
|
return decodedToken.exp < Date.now() / 1000;
|
|
700
658
|
}
|
|
701
|
-
checkMetadataAccessTokenExpired() {
|
|
702
|
-
try {
|
|
703
|
-
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
|
|
704
|
-
const { metadataAccessToken } = this.state;
|
|
705
|
-
if (!metadataAccessToken) {
|
|
706
|
-
return true; // Consider missing token as expired
|
|
707
|
-
}
|
|
708
|
-
const decodedToken = this.decodeJWTToken(metadataAccessToken);
|
|
709
|
-
return decodedToken.exp < Math.floor(Date.now() / 1000);
|
|
710
|
-
}
|
|
711
|
-
catch {
|
|
712
|
-
return true; // Consider unauthenticated user as having expired tokens
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
checkAccessTokenExpired() {
|
|
716
|
-
try {
|
|
717
|
-
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
|
|
718
|
-
const { accessToken } = this.state;
|
|
719
|
-
if (!accessToken) {
|
|
720
|
-
return true; // Consider missing token as expired
|
|
721
|
-
}
|
|
722
|
-
const decodedToken = this.decodeJWTToken(accessToken);
|
|
723
|
-
return decodedToken.exp < Math.floor(Date.now() / 1000);
|
|
724
|
-
}
|
|
725
|
-
catch {
|
|
726
|
-
return true; // Consider unauthenticated user as having expired tokens
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
659
|
/**
|
|
730
660
|
* Decode the node auth token from base64 to json object.
|
|
731
661
|
*
|
|
@@ -735,30 +665,6 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
735
665
|
decodeNodeAuthToken(token) {
|
|
736
666
|
return JSON.parse((0, utils_2.bytesToUtf8)((0, utils_1.base64ToBytes)(token)));
|
|
737
667
|
}
|
|
738
|
-
/**
|
|
739
|
-
* Decode JWT token
|
|
740
|
-
*
|
|
741
|
-
* @param token - The JWT token to decode.
|
|
742
|
-
* @returns The decoded JWT token.
|
|
743
|
-
*/
|
|
744
|
-
decodeJWTToken(token) {
|
|
745
|
-
// JWT tokens have 3 parts separated by dots: header.payload.signature
|
|
746
|
-
const parts = token.split('.');
|
|
747
|
-
if (parts.length !== 3) {
|
|
748
|
-
throw new Error('Invalid JWT token format');
|
|
749
|
-
}
|
|
750
|
-
// Decode the payload (second part)
|
|
751
|
-
const payload = parts[1];
|
|
752
|
-
// Add padding if needed for base64 decoding
|
|
753
|
-
const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
|
|
754
|
-
try {
|
|
755
|
-
const decoded = JSON.parse(Buffer.from(paddedPayload, 'base64').toString());
|
|
756
|
-
return decoded;
|
|
757
|
-
}
|
|
758
|
-
catch (error) {
|
|
759
|
-
throw new Error(`Failed to decode JWT token: ${error instanceof Error ? error.message : String(error)}`);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
668
|
}
|
|
763
669
|
exports.SeedlessOnboardingController = SeedlessOnboardingController;
|
|
764
670
|
_SeedlessOnboardingController_vaultEncryptor = new WeakMap(), _SeedlessOnboardingController_controllerOperationMutex = new WeakMap(), _SeedlessOnboardingController_vaultOperationMutex = new WeakMap(), _SeedlessOnboardingController_refreshJWTToken = new WeakMap(), _SeedlessOnboardingController_revokeRefreshToken = new WeakMap(), _SeedlessOnboardingController_isUnlocked = new WeakMap(), _SeedlessOnboardingController_instances = new WeakSet(), _SeedlessOnboardingController_submitGlobalPassword =
|
|
@@ -1013,6 +919,7 @@ async function _SeedlessOnboardingController_encryptAndStoreSecretData(params) {
|
|
|
1013
919
|
* @param password - The optional password to unlock the vault.
|
|
1014
920
|
* @param encryptionKey - The optional encryption key to unlock the vault.
|
|
1015
921
|
* @returns A promise that resolves to an object containing:
|
|
922
|
+
* - nodeAuthTokens: Authentication tokens to communicate with the TOPRF service
|
|
1016
923
|
* - toprfEncryptionKey: The decrypted TOPRF encryption key
|
|
1017
924
|
* - toprfAuthKeyPair: The decrypted TOPRF authentication key pair
|
|
1018
925
|
* @throws {Error} If:
|
|
@@ -1055,19 +962,20 @@ async function _SeedlessOnboardingController_unlockVaultAndGetBackupEncKey(passw
|
|
|
1055
962
|
updatedState.vaultEncryptionKey = vaultEncryptionKey;
|
|
1056
963
|
updatedState.vaultEncryptionSalt = vaultEncryptionSalt;
|
|
1057
964
|
}
|
|
1058
|
-
const { toprfEncryptionKey, toprfPwEncryptionKey, toprfAuthKeyPair, revokeToken,
|
|
965
|
+
const { nodeAuthTokens, toprfEncryptionKey, toprfPwEncryptionKey, toprfAuthKeyPair, revokeToken, } = __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_parseVaultData).call(this, decryptedVaultData);
|
|
966
|
+
// update the state with the restored nodeAuthTokens
|
|
1059
967
|
this.update((state) => {
|
|
968
|
+
state.nodeAuthTokens = nodeAuthTokens;
|
|
1060
969
|
state.vaultEncryptionKey = updatedState.vaultEncryptionKey;
|
|
1061
970
|
state.vaultEncryptionSalt = updatedState.vaultEncryptionSalt;
|
|
1062
971
|
state.revokeToken = revokeToken;
|
|
1063
|
-
state.accessToken = accessToken;
|
|
1064
972
|
});
|
|
1065
973
|
return {
|
|
974
|
+
nodeAuthTokens,
|
|
1066
975
|
toprfEncryptionKey,
|
|
1067
976
|
toprfPwEncryptionKey,
|
|
1068
977
|
toprfAuthKeyPair,
|
|
1069
978
|
revokeToken,
|
|
1070
|
-
accessToken,
|
|
1071
979
|
};
|
|
1072
980
|
});
|
|
1073
981
|
}, _SeedlessOnboardingController_withPersistedSecretMetadataBackupsState =
|
|
@@ -1143,17 +1051,14 @@ async function _SeedlessOnboardingController_createNewVaultWithAuthData({ passwo
|
|
|
1143
1051
|
if (!this.state.revokeToken) {
|
|
1144
1052
|
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidRevokeToken);
|
|
1145
1053
|
}
|
|
1146
|
-
if (!this.state.accessToken) {
|
|
1147
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidAccessToken);
|
|
1148
|
-
}
|
|
1149
1054
|
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_setUnlocked).call(this);
|
|
1150
1055
|
const { toprfEncryptionKey, toprfPwEncryptionKey, toprfAuthKeyPair } = __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_serializeKeyData).call(this, rawToprfEncryptionKey, rawToprfPwEncryptionKey, rawToprfAuthKeyPair);
|
|
1151
1056
|
const serializedVaultData = JSON.stringify({
|
|
1057
|
+
authTokens: this.state.nodeAuthTokens,
|
|
1152
1058
|
toprfEncryptionKey,
|
|
1153
1059
|
toprfPwEncryptionKey,
|
|
1154
1060
|
toprfAuthKeyPair,
|
|
1155
1061
|
revokeToken: this.state.revokeToken,
|
|
1156
|
-
accessToken: this.state.accessToken,
|
|
1157
1062
|
});
|
|
1158
1063
|
await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_updateVault).call(this, {
|
|
1159
1064
|
password,
|
|
@@ -1252,11 +1157,11 @@ async function _SeedlessOnboardingController_withVaultLock(callback) {
|
|
|
1252
1157
|
pk: (0, utils_1.base64ToBytes)(parsedToprfAuthKeyPair.pk),
|
|
1253
1158
|
};
|
|
1254
1159
|
return {
|
|
1160
|
+
nodeAuthTokens: parsedVaultData.authTokens,
|
|
1255
1161
|
toprfEncryptionKey: rawToprfEncryptionKey,
|
|
1256
1162
|
toprfPwEncryptionKey: rawToprfPwEncryptionKey,
|
|
1257
1163
|
toprfAuthKeyPair: rawToprfAuthKeyPair,
|
|
1258
1164
|
revokeToken: parsedVaultData.revokeToken,
|
|
1259
|
-
accessToken: parsedVaultData.accessToken,
|
|
1260
1165
|
};
|
|
1261
1166
|
}, _SeedlessOnboardingController_assertIsUnlocked = function _SeedlessOnboardingController_assertIsUnlocked() {
|
|
1262
1167
|
if (!__classPrivateFieldGet(this, _SeedlessOnboardingController_isUnlocked, "f")) {
|
|
@@ -1281,10 +1186,6 @@ async function _SeedlessOnboardingController_withVaultLock(callback) {
|
|
|
1281
1186
|
if (!('refreshToken' in value) || typeof value.refreshToken !== 'string') {
|
|
1282
1187
|
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidRefreshToken);
|
|
1283
1188
|
}
|
|
1284
|
-
if (!('metadataAccessToken' in value) ||
|
|
1285
|
-
typeof value.metadataAccessToken !== 'string') {
|
|
1286
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidMetadataAccessToken);
|
|
1287
|
-
}
|
|
1288
1189
|
}, _SeedlessOnboardingController_assertIsSRPBackedUpUser = function _SeedlessOnboardingController_assertIsSRPBackedUpUser(value) {
|
|
1289
1190
|
if (!this.state.authPubKey) {
|
|
1290
1191
|
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.SRPNotBackedUpError);
|
|
@@ -1311,6 +1212,8 @@ async function _SeedlessOnboardingController_assertPasswordInSync(options) {
|
|
|
1311
1212
|
// value is not valid vault data if any of the following conditions are true:
|
|
1312
1213
|
if (!value || // value is not defined
|
|
1313
1214
|
typeof value !== 'object' || // value is not an object
|
|
1215
|
+
!('authTokens' in value) || // authTokens is not defined
|
|
1216
|
+
typeof value.authTokens !== 'object' || // authTokens is not an object
|
|
1314
1217
|
!('toprfEncryptionKey' in value) || // toprfEncryptionKey is not defined
|
|
1315
1218
|
typeof value.toprfEncryptionKey !== 'string' || // toprfEncryptionKey is not a string
|
|
1316
1219
|
!('toprfPwEncryptionKey' in value) || // toprfPwEncryptionKey is not defined
|
|
@@ -1318,9 +1221,7 @@ async function _SeedlessOnboardingController_assertPasswordInSync(options) {
|
|
|
1318
1221
|
!('toprfAuthKeyPair' in value) || // toprfAuthKeyPair is not defined
|
|
1319
1222
|
typeof value.toprfAuthKeyPair !== 'string' || // toprfAuthKeyPair is not a string
|
|
1320
1223
|
!('revokeToken' in value) || // revokeToken is not defined
|
|
1321
|
-
typeof value.revokeToken !== 'string'
|
|
1322
|
-
!('accessToken' in value) || // accessToken is not defined
|
|
1323
|
-
typeof value.accessToken !== 'string' // accessToken is not a string
|
|
1224
|
+
typeof value.revokeToken !== 'string' // revokeToken is not a string
|
|
1324
1225
|
) {
|
|
1325
1226
|
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.VaultDataError);
|
|
1326
1227
|
}
|
|
@@ -1347,13 +1248,9 @@ async function _SeedlessOnboardingController_executeWithTokenRefresh(operation,
|
|
|
1347
1248
|
try {
|
|
1348
1249
|
// proactively check for expired tokens and refresh them if needed
|
|
1349
1250
|
const isNodeAuthTokenExpired = this.checkNodeAuthTokenExpired();
|
|
1350
|
-
|
|
1351
|
-
const isAccessTokenExpired = this.checkAccessTokenExpired();
|
|
1352
|
-
if (isNodeAuthTokenExpired ||
|
|
1353
|
-
isMetadataAccessTokenExpired ||
|
|
1354
|
-
isAccessTokenExpired) {
|
|
1251
|
+
if (isNodeAuthTokenExpired) {
|
|
1355
1252
|
log(`JWT token expired during ${operationName}, attempting to refresh tokens`, 'node auth token exp check');
|
|
1356
|
-
await this.
|
|
1253
|
+
await this.refreshNodeAuthTokens();
|
|
1357
1254
|
}
|
|
1358
1255
|
return await operation();
|
|
1359
1256
|
}
|
|
@@ -1363,7 +1260,7 @@ async function _SeedlessOnboardingController_executeWithTokenRefresh(operation,
|
|
|
1363
1260
|
log(`Token expired during ${operationName}, attempting to refresh tokens`, error);
|
|
1364
1261
|
try {
|
|
1365
1262
|
// Refresh the tokens
|
|
1366
|
-
await this.
|
|
1263
|
+
await this.refreshNodeAuthTokens();
|
|
1367
1264
|
// Retry the operation with fresh tokens
|
|
1368
1265
|
return await operation();
|
|
1369
1266
|
}
|