@metamask-previews/seedless-onboarding-controller 7.1.0-preview-bc3c2ef97 → 7.1.0-preview-0bb0ab8a7
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 +12 -0
- package/dist/SeedlessOnboardingController.cjs +138 -49
- package/dist/SeedlessOnboardingController.cjs.map +1 -1
- package/dist/SeedlessOnboardingController.d.cts +86 -3
- package/dist/SeedlessOnboardingController.d.cts.map +1 -1
- package/dist/SeedlessOnboardingController.d.mts +86 -3
- package/dist/SeedlessOnboardingController.d.mts.map +1 -1
- package/dist/SeedlessOnboardingController.mjs +139 -50
- package/dist/SeedlessOnboardingController.mjs.map +1 -1
- package/dist/assertions.cjs +16 -1
- package/dist/assertions.cjs.map +1 -1
- package/dist/assertions.d.cts +7 -0
- package/dist/assertions.d.cts.map +1 -1
- package/dist/assertions.d.mts +7 -0
- package/dist/assertions.d.mts.map +1 -1
- package/dist/assertions.mjs +14 -0
- package/dist/assertions.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -67
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +2 -67
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils.cjs +31 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +8 -0
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts +8 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +29 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ 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
|
+
- **BREAKING** The `encryptor` constructor param requires `encryptWithKey` method. ([#7800](https://github.com/MetaMask/core/pull/7800))
|
|
13
|
+
- The method is to encrypt the vault with cached encryption key while the wallet is unlocked.
|
|
14
|
+
- Added new public method, `getAccessToken`. ([#7800](https://github.com/MetaMask/core/pull/7800))
|
|
15
|
+
- Clients can use this method to get `accessToken` from the controller, instead of directly accessing from the state.
|
|
16
|
+
- This method also adds refresh token mechanism when `accessToken` is expired, hence preventing expired token usage in the clients.
|
|
17
|
+
|
|
10
18
|
### Changed
|
|
11
19
|
|
|
12
20
|
- Update StateMetadata's `includeInStateLogs` property. ([#7750](https://github.com/MetaMask/core/pull/7750))
|
|
@@ -14,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
14
22
|
- Bump `@metamask/keyring-controller` from `^25.0.0` to `^25.1.0` ([#7713](https://github.com/MetaMask/core/pull/7713))
|
|
15
23
|
- Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
|
|
16
24
|
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fixed new `accessToken` not being persisted in the vault after the token refresh. ([#7800](https://github.com/MetaMask/core/pull/7800))
|
|
28
|
+
|
|
17
29
|
## [7.1.0]
|
|
18
30
|
|
|
19
31
|
### Added
|
|
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _SeedlessOnboardingController_instances, _SeedlessOnboardingController_vaultEncryptor, _SeedlessOnboardingController_controllerOperationMutex, _SeedlessOnboardingController_vaultOperationMutex, _SeedlessOnboardingController_refreshJWTToken, _SeedlessOnboardingController_revokeRefreshToken, _SeedlessOnboardingController_renewRefreshToken, _SeedlessOnboardingController_passwordOutdatedCacheTTL, _SeedlessOnboardingController_isUnlocked, _SeedlessOnboardingController_cachedDecryptedVaultData, _SeedlessOnboardingController_submitGlobalPassword, _SeedlessOnboardingController_setUnlocked, _SeedlessOnboardingController_persistOprfKey, _SeedlessOnboardingController_persistAuthPubKey, _SeedlessOnboardingController_storeKeyringEncryptionKey, _SeedlessOnboardingController_loadKeyringEncryptionKey, _SeedlessOnboardingController_loadSeedlessEncryptionKey, _SeedlessOnboardingController_recoverAuthPubKey, _SeedlessOnboardingController_recoverEncKey, _SeedlessOnboardingController_fetchAllSecretDataFromMetadataStore, _SeedlessOnboardingController_changeEncryptionKey, _SeedlessOnboardingController_encryptAndStoreSecretData, _SeedlessOnboardingController_unlockVaultAndGetVaultData, _SeedlessOnboardingController_decryptAndParseVaultData, _SeedlessOnboardingController_withPersistedSecretMetadataBackupsState, _SeedlessOnboardingController_filterDupesAndUpdateSocialBackupsMetadata, _SeedlessOnboardingController_createNewVaultWithAuthData, _SeedlessOnboardingController_updateVault, _SeedlessOnboardingController_getAccessTokenAndRevokeToken, _SeedlessOnboardingController_withControllerLock, _SeedlessOnboardingController_withVaultLock, _SeedlessOnboardingController_parseVaultData, _SeedlessOnboardingController_assertIsUnlocked, _SeedlessOnboardingController_assertIsAuthenticatedUser, _SeedlessOnboardingController_assertPasswordInSync, _SeedlessOnboardingController_resetPasswordOutdatedCache, _SeedlessOnboardingController_addRefreshTokenToRevokeList, _SeedlessOnboardingController_isAuthTokenError, _SeedlessOnboardingController_isMaxKeyChainLengthError, _SeedlessOnboardingController_executeWithTokenRefresh;
|
|
13
|
+
var _SeedlessOnboardingController_instances, _SeedlessOnboardingController_vaultEncryptor, _SeedlessOnboardingController_controllerOperationMutex, _SeedlessOnboardingController_vaultOperationMutex, _SeedlessOnboardingController_refreshJWTToken, _SeedlessOnboardingController_revokeRefreshToken, _SeedlessOnboardingController_renewRefreshToken, _SeedlessOnboardingController_passwordOutdatedCacheTTL, _SeedlessOnboardingController_isUnlocked, _SeedlessOnboardingController_cachedDecryptedVaultData, _SeedlessOnboardingController_submitGlobalPassword, _SeedlessOnboardingController_setUnlocked, _SeedlessOnboardingController_pickLatestAccessToken, _SeedlessOnboardingController_persistOprfKey, _SeedlessOnboardingController_persistAuthPubKey, _SeedlessOnboardingController_storeKeyringEncryptionKey, _SeedlessOnboardingController_loadKeyringEncryptionKey, _SeedlessOnboardingController_loadSeedlessEncryptionKey, _SeedlessOnboardingController_recoverAuthPubKey, _SeedlessOnboardingController_recoverEncKey, _SeedlessOnboardingController_fetchAllSecretDataFromMetadataStore, _SeedlessOnboardingController_changeEncryptionKey, _SeedlessOnboardingController_encryptAndStoreSecretData, _SeedlessOnboardingController_unlockVaultAndGetVaultData, _SeedlessOnboardingController_decryptAndParseVaultData, _SeedlessOnboardingController_withPersistedSecretMetadataBackupsState, _SeedlessOnboardingController_filterDupesAndUpdateSocialBackupsMetadata, _SeedlessOnboardingController_createNewVaultWithAuthData, _SeedlessOnboardingController_updateVault, _SeedlessOnboardingController_encryptSeedlessEncryptionKey, _SeedlessOnboardingController_getAccessTokenAndRevokeToken, _SeedlessOnboardingController_withControllerLock, _SeedlessOnboardingController_withVaultLock, _SeedlessOnboardingController_parseVaultData, _SeedlessOnboardingController_assertIsUnlocked, _SeedlessOnboardingController_assertIsAuthenticatedUser, _SeedlessOnboardingController_assertPasswordInSync, _SeedlessOnboardingController_resetPasswordOutdatedCache, _SeedlessOnboardingController_addRefreshTokenToRevokeList, _SeedlessOnboardingController_isAuthTokenError, _SeedlessOnboardingController_isMaxKeyChainLengthError, _SeedlessOnboardingController_executeWithTokenRefresh, _SeedlessOnboardingController_checkTokensExpired;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.SeedlessOnboardingController = exports.getInitialSeedlessOnboardingControllerStateWithDefaults = void 0;
|
|
16
16
|
const auth_network_utils_1 = require("@metamask/auth-network-utils");
|
|
@@ -242,6 +242,7 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
242
242
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_refreshJWTToken, refreshJWTToken, "f");
|
|
243
243
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_revokeRefreshToken, revokeRefreshToken, "f");
|
|
244
244
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_renewRefreshToken, renewRefreshToken, "f");
|
|
245
|
+
this.messenger.registerActionHandler(`${constants_1.controllerName}:getAccessToken`, this.getAccessToken.bind(this));
|
|
245
246
|
}
|
|
246
247
|
async fetchMetadataAccessCreds() {
|
|
247
248
|
const { metadataAccessToken } = this.state;
|
|
@@ -552,7 +553,7 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
552
553
|
/**
|
|
553
554
|
* Submit the password to the controller, verify the password validity and unlock the controller.
|
|
554
555
|
*
|
|
555
|
-
* This method will be used especially when user
|
|
556
|
+
* This method will be used especially when user unlock the wallet.
|
|
556
557
|
* The provided password will be verified against the encrypted vault, encryption key will be derived and saved in the controller state.
|
|
557
558
|
*
|
|
558
559
|
* This operation is useful when user performs some actions that requires the user password/encryption key. e.g. add new srp backup
|
|
@@ -562,7 +563,27 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
562
563
|
*/
|
|
563
564
|
async submitPassword(password) {
|
|
564
565
|
return await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_withControllerLock).call(this, async () => {
|
|
565
|
-
|
|
566
|
+
// get the access token from the state before unlocking, it might be the new token set from the `refreshAuthTokens` method.
|
|
567
|
+
const { accessToken: accessTokenBeforeUnlock } = this.state;
|
|
568
|
+
const deserializedVaultData = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_unlockVaultAndGetVaultData).call(this, {
|
|
569
|
+
password,
|
|
570
|
+
});
|
|
571
|
+
const accessTokenFromDecryptedVault = deserializedVaultData.accessToken;
|
|
572
|
+
// Pick the latest access token - the token from state might be newer (from refreshAuthTokens)
|
|
573
|
+
// than the token stored in the vault.
|
|
574
|
+
const latestAccessToken = __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_pickLatestAccessToken).call(this, accessTokenBeforeUnlock, accessTokenFromDecryptedVault);
|
|
575
|
+
// update the state and vault with the latest access token `ONLY` if it's different from the current access token in the state.
|
|
576
|
+
if (latestAccessToken !== accessTokenFromDecryptedVault) {
|
|
577
|
+
const updatedVaultData = {
|
|
578
|
+
...deserializedVaultData,
|
|
579
|
+
accessToken: latestAccessToken,
|
|
580
|
+
};
|
|
581
|
+
await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_updateVault).call(this, {
|
|
582
|
+
password,
|
|
583
|
+
vaultData: updatedVaultData,
|
|
584
|
+
pwEncKey: deserializedVaultData.toprfPwEncryptionKey,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
566
587
|
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_setUnlocked).call(this);
|
|
567
588
|
});
|
|
568
589
|
}
|
|
@@ -768,6 +789,18 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
768
789
|
refreshToken,
|
|
769
790
|
skipLock: true,
|
|
770
791
|
});
|
|
792
|
+
// update the vault with new access token if wallet is unlocked
|
|
793
|
+
if (__classPrivateFieldGet(this, _SeedlessOnboardingController_isUnlocked, "f") && __classPrivateFieldGet(this, _SeedlessOnboardingController_cachedDecryptedVaultData, "f")) {
|
|
794
|
+
const updatedVaultData = {
|
|
795
|
+
...__classPrivateFieldGet(this, _SeedlessOnboardingController_cachedDecryptedVaultData, "f"),
|
|
796
|
+
accessToken,
|
|
797
|
+
};
|
|
798
|
+
const pwEncKey = __classPrivateFieldGet(this, _SeedlessOnboardingController_cachedDecryptedVaultData, "f").toprfPwEncryptionKey;
|
|
799
|
+
await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_updateVault).call(this, {
|
|
800
|
+
vaultData: updatedVaultData,
|
|
801
|
+
pwEncKey,
|
|
802
|
+
});
|
|
803
|
+
}
|
|
771
804
|
}
|
|
772
805
|
catch (error) {
|
|
773
806
|
log('Error refreshing node auth tokens', error);
|
|
@@ -858,6 +891,21 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
|
|
|
858
891
|
}
|
|
859
892
|
});
|
|
860
893
|
}
|
|
894
|
+
/**
|
|
895
|
+
* Get the access token from the state.
|
|
896
|
+
*
|
|
897
|
+
* If the tokens are expired, the method will refresh them and return the new access token.
|
|
898
|
+
*
|
|
899
|
+
* @returns The access token.
|
|
900
|
+
*/
|
|
901
|
+
async getAccessToken() {
|
|
902
|
+
return __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_withControllerLock).call(this, async () => {
|
|
903
|
+
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
|
|
904
|
+
return __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_executeWithTokenRefresh).call(this, async () => {
|
|
905
|
+
return this.state.accessToken;
|
|
906
|
+
}, 'getAccessToken');
|
|
907
|
+
});
|
|
908
|
+
}
|
|
861
909
|
/**
|
|
862
910
|
* Check if the current node auth token is expired.
|
|
863
911
|
*
|
|
@@ -926,22 +974,28 @@ _SeedlessOnboardingController_vaultEncryptor = new WeakMap(), _SeedlessOnboardin
|
|
|
926
974
|
* corresponding to the current authPubKey in state.
|
|
927
975
|
*/
|
|
928
976
|
async function _SeedlessOnboardingController_submitGlobalPassword({ targetAuthPubKey, globalPassword, maxKeyChainLength, }) {
|
|
929
|
-
const { pwEncKey:
|
|
977
|
+
const { pwEncKey: globalPwEncKey, authKeyPair: globalAuthKeyPair } = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_recoverEncKey).call(this, globalPassword);
|
|
930
978
|
try {
|
|
931
979
|
// Recover vault encryption key.
|
|
932
980
|
const res = await this.toprfClient.recoverPwEncKey({
|
|
933
981
|
targetAuthPubKey,
|
|
934
|
-
curPwEncKey,
|
|
935
|
-
curAuthKeyPair,
|
|
982
|
+
curPwEncKey: globalPwEncKey,
|
|
983
|
+
curAuthKeyPair: globalAuthKeyPair,
|
|
936
984
|
maxPwChainLength: maxKeyChainLength,
|
|
937
985
|
});
|
|
938
986
|
const { pwEncKey } = res;
|
|
939
987
|
const vaultKey = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_loadSeedlessEncryptionKey).call(this, pwEncKey);
|
|
988
|
+
// accessToken before unlocking vault and flooding the state with values from the decrypted vault
|
|
989
|
+
// it might be the new token set from the `refreshAuthTokens` method.
|
|
990
|
+
const { accessToken: accessTokenBeforeUnlock } = this.state;
|
|
940
991
|
// Unlock the controller
|
|
941
|
-
await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_unlockVaultAndGetVaultData).call(this, {
|
|
992
|
+
const decryptedVaultData = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_unlockVaultAndGetVaultData).call(this, {
|
|
942
993
|
encryptionKey: vaultKey,
|
|
943
994
|
});
|
|
944
995
|
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_setUnlocked).call(this);
|
|
996
|
+
// Pick the latest access token - the token from state might be newer (from refreshAuthTokens)
|
|
997
|
+
// than the token stored in the vault. The vault will be updated later by syncLatestGlobalPassword.
|
|
998
|
+
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_pickLatestAccessToken).call(this, accessTokenBeforeUnlock, decryptedVaultData.accessToken);
|
|
945
999
|
}
|
|
946
1000
|
catch (error) {
|
|
947
1001
|
if (__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_isAuthTokenError).call(this, error)) {
|
|
@@ -954,6 +1008,18 @@ async function _SeedlessOnboardingController_submitGlobalPassword({ targetAuthPu
|
|
|
954
1008
|
}
|
|
955
1009
|
}, _SeedlessOnboardingController_setUnlocked = function _SeedlessOnboardingController_setUnlocked() {
|
|
956
1010
|
__classPrivateFieldSet(this, _SeedlessOnboardingController_isUnlocked, true, "f");
|
|
1011
|
+
}, _SeedlessOnboardingController_pickLatestAccessToken = function _SeedlessOnboardingController_pickLatestAccessToken(tokenBeforeUnlock, tokenAfterUnlock) {
|
|
1012
|
+
let latestToken = tokenAfterUnlock;
|
|
1013
|
+
if (tokenBeforeUnlock &&
|
|
1014
|
+
tokenAfterUnlock &&
|
|
1015
|
+
tokenBeforeUnlock !== tokenAfterUnlock) {
|
|
1016
|
+
latestToken = (0, utils_3.compareAndGetLatestToken)(tokenBeforeUnlock, tokenAfterUnlock);
|
|
1017
|
+
// Update the access token in the state with the latest access token
|
|
1018
|
+
this.update((state) => {
|
|
1019
|
+
state.accessToken = latestToken;
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
return latestToken;
|
|
957
1023
|
}, _SeedlessOnboardingController_persistOprfKey =
|
|
958
1024
|
/**
|
|
959
1025
|
* Persist the encryption key for the seedless onboarding flow.
|
|
@@ -1248,7 +1314,7 @@ async function _SeedlessOnboardingController_decryptAndParseVaultData(params) {
|
|
|
1248
1314
|
}
|
|
1249
1315
|
else {
|
|
1250
1316
|
// if the encryption key is not available, we will use the password to decrypt the vault
|
|
1251
|
-
assertIsValidPassword(params?.password);
|
|
1317
|
+
(0, assertions_1.assertIsValidPassword)(params?.password);
|
|
1252
1318
|
// Note that vault decryption using the password is a very costly operation as it involves deriving the encryption key
|
|
1253
1319
|
// from the password using an intentionally slow key derivation function.
|
|
1254
1320
|
// We should make sure that we only call it very intentionally.
|
|
@@ -1356,31 +1422,66 @@ async function _SeedlessOnboardingController_createNewVaultWithAuthData({ passwo
|
|
|
1356
1422
|
* Encrypt and update the vault with the given authentication data.
|
|
1357
1423
|
*
|
|
1358
1424
|
* @param params - The parameters for updating the vault.
|
|
1359
|
-
* @param params.password - The password to encrypt the vault.
|
|
1425
|
+
* @param params.password - The optional password to encrypt the vault. If not provided, the vault will be encrypted with the encryption key in the state.
|
|
1360
1426
|
* @param params.vaultData - The raw vault data to update the vault with.
|
|
1361
1427
|
* @param params.pwEncKey - The global password encryption key.
|
|
1362
1428
|
* @returns A promise that resolves to the updated vault.
|
|
1363
1429
|
*/
|
|
1364
1430
|
async function _SeedlessOnboardingController_updateVault({ password, vaultData, pwEncKey, }) {
|
|
1365
1431
|
await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_withVaultLock).call(this, async () => {
|
|
1366
|
-
assertIsValidPassword(password);
|
|
1367
|
-
// cache the vault data to avoid decrypting the vault data multiple times
|
|
1368
|
-
__classPrivateFieldSet(this, _SeedlessOnboardingController_cachedDecryptedVaultData, vaultData, "f");
|
|
1369
1432
|
const serializedVaultData = (0, utils_3.serializeVaultData)(vaultData);
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1433
|
+
const { vaultEncryptionKey, vaultEncryptionSalt, vault } = this.state;
|
|
1434
|
+
const updatedState = {
|
|
1435
|
+
vault,
|
|
1436
|
+
vaultEncryptionKey,
|
|
1437
|
+
vaultEncryptionSalt,
|
|
1438
|
+
encryptedSeedlessEncryptionKey: this.state.encryptedSeedlessEncryptionKey,
|
|
1439
|
+
};
|
|
1440
|
+
// if the password is provided (not undefined), encrypt the vault with the password
|
|
1441
|
+
// We gonna prioritize the password encryption here, in case of the operation is `Change Password`.
|
|
1442
|
+
// We don't wanna re-use the old encryption key from the state.
|
|
1443
|
+
if (password !== undefined) {
|
|
1444
|
+
(0, assertions_1.assertIsValidPassword)(password);
|
|
1445
|
+
// Note that vault encryption using the password is a very costly operation as it involves deriving the encryption key
|
|
1446
|
+
// from the password using an intentionally slow key derivation function.
|
|
1447
|
+
// We should make sure that we only call it very intentionally.
|
|
1448
|
+
const { vault: updatedEncVault, exportedKeyString } = await __classPrivateFieldGet(this, _SeedlessOnboardingController_vaultEncryptor, "f").encryptWithDetail(password, serializedVaultData);
|
|
1449
|
+
updatedState.vault = updatedEncVault;
|
|
1450
|
+
updatedState.vaultEncryptionKey = exportedKeyString;
|
|
1451
|
+
updatedState.vaultEncryptionSalt = JSON.parse(updatedEncVault).salt;
|
|
1452
|
+
// encrypt the seedless encryption key with the password encryption key from TOPRF network
|
|
1453
|
+
updatedState.encryptedSeedlessEncryptionKey =
|
|
1454
|
+
__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_encryptSeedlessEncryptionKey).call(this, exportedKeyString, pwEncKey);
|
|
1455
|
+
}
|
|
1456
|
+
else if (vaultEncryptionKey && vaultEncryptionSalt) {
|
|
1457
|
+
const encryptionKey = await __classPrivateFieldGet(this, _SeedlessOnboardingController_vaultEncryptor, "f").importKey(vaultEncryptionKey);
|
|
1458
|
+
const updatedEncVault = await __classPrivateFieldGet(this, _SeedlessOnboardingController_vaultEncryptor, "f").encryptWithKey(encryptionKey, serializedVaultData);
|
|
1459
|
+
// NOTE: Referenced from keyring-controller!
|
|
1460
|
+
// We need to include the salt used to derive the encryption key, to be able to derive it from password again.
|
|
1461
|
+
updatedEncVault.salt = vaultEncryptionSalt;
|
|
1462
|
+
updatedState.vault = JSON.stringify(updatedEncVault);
|
|
1463
|
+
updatedState.vaultEncryptionKey = vaultEncryptionKey;
|
|
1464
|
+
updatedState.vaultEncryptionSalt = vaultEncryptionSalt;
|
|
1465
|
+
}
|
|
1466
|
+
else {
|
|
1467
|
+
// neither password nor encryption key is provided
|
|
1468
|
+
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.MissingCredentials);
|
|
1469
|
+
}
|
|
1470
|
+
// update the state with the updated vault data
|
|
1377
1471
|
this.update((state) => {
|
|
1378
|
-
state.vault = vault;
|
|
1379
|
-
state.vaultEncryptionKey =
|
|
1380
|
-
state.vaultEncryptionSalt =
|
|
1381
|
-
state.encryptedSeedlessEncryptionKey =
|
|
1472
|
+
state.vault = updatedState.vault;
|
|
1473
|
+
state.vaultEncryptionKey = updatedState.vaultEncryptionKey;
|
|
1474
|
+
state.vaultEncryptionSalt = updatedState.vaultEncryptionSalt;
|
|
1475
|
+
state.encryptedSeedlessEncryptionKey =
|
|
1476
|
+
updatedState.encryptedSeedlessEncryptionKey;
|
|
1382
1477
|
});
|
|
1478
|
+
// cache the vault data to avoid decrypting the vault data multiple times
|
|
1479
|
+
__classPrivateFieldSet(this, _SeedlessOnboardingController_cachedDecryptedVaultData, vaultData, "f");
|
|
1383
1480
|
});
|
|
1481
|
+
}, _SeedlessOnboardingController_encryptSeedlessEncryptionKey = function _SeedlessOnboardingController_encryptSeedlessEncryptionKey(vaultEncryptionKey, pwEncKey) {
|
|
1482
|
+
const aes = (0, webcrypto_1.managedNonce)(aes_1.gcm)(pwEncKey);
|
|
1483
|
+
const encryptedKey = aes.encrypt((0, utils_2.utf8ToBytes)(vaultEncryptionKey));
|
|
1484
|
+
return (0, utils_1.bytesToBase64)(encryptedKey);
|
|
1384
1485
|
}, _SeedlessOnboardingController_getAccessTokenAndRevokeToken =
|
|
1385
1486
|
/**
|
|
1386
1487
|
* Get the access token and revoke token from the state or the vault.
|
|
@@ -1537,18 +1638,7 @@ async function _SeedlessOnboardingController_assertPasswordInSync(options) {
|
|
|
1537
1638
|
*/
|
|
1538
1639
|
async function _SeedlessOnboardingController_executeWithTokenRefresh(operation, operationName) {
|
|
1539
1640
|
try {
|
|
1540
|
-
|
|
1541
|
-
const isNodeAuthTokenExpired = this.checkNodeAuthTokenExpired();
|
|
1542
|
-
const isMetadataAccessTokenExpired = this.checkMetadataAccessTokenExpired();
|
|
1543
|
-
// access token is only accessible when the vault is unlocked
|
|
1544
|
-
// so skip the check if the vault is locked
|
|
1545
|
-
let isAccessTokenExpired = false;
|
|
1546
|
-
if (__classPrivateFieldGet(this, _SeedlessOnboardingController_isUnlocked, "f")) {
|
|
1547
|
-
isAccessTokenExpired = this.checkAccessTokenExpired();
|
|
1548
|
-
}
|
|
1549
|
-
if (isNodeAuthTokenExpired ||
|
|
1550
|
-
isMetadataAccessTokenExpired ||
|
|
1551
|
-
isAccessTokenExpired) {
|
|
1641
|
+
if (__classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_checkTokensExpired).call(this)) {
|
|
1552
1642
|
log(`JWT token expired during ${operationName}, attempting to refresh tokens`, 'node auth token exp check');
|
|
1553
1643
|
await this.refreshAuthTokens();
|
|
1554
1644
|
}
|
|
@@ -1574,21 +1664,20 @@ async function _SeedlessOnboardingController_executeWithTokenRefresh(operation,
|
|
|
1574
1664
|
throw error;
|
|
1575
1665
|
}
|
|
1576
1666
|
}
|
|
1667
|
+
}, _SeedlessOnboardingController_checkTokensExpired = function _SeedlessOnboardingController_checkTokensExpired() {
|
|
1668
|
+
// proactively check for expired tokens and refresh them if needed
|
|
1669
|
+
const isNodeAuthTokenExpired = this.checkNodeAuthTokenExpired();
|
|
1670
|
+
const isMetadataAccessTokenExpired = this.checkMetadataAccessTokenExpired();
|
|
1671
|
+
// access token is only accessible when the vault is unlocked
|
|
1672
|
+
// so skip the check if the vault is locked
|
|
1673
|
+
let isAccessTokenExpired = false;
|
|
1674
|
+
if (__classPrivateFieldGet(this, _SeedlessOnboardingController_isUnlocked, "f")) {
|
|
1675
|
+
isAccessTokenExpired = this.checkAccessTokenExpired();
|
|
1676
|
+
}
|
|
1677
|
+
return (isNodeAuthTokenExpired ||
|
|
1678
|
+
isMetadataAccessTokenExpired ||
|
|
1679
|
+
isAccessTokenExpired);
|
|
1577
1680
|
};
|
|
1578
|
-
/**
|
|
1579
|
-
* Assert that the provided password is a valid non-empty string.
|
|
1580
|
-
*
|
|
1581
|
-
* @param password - The password to check.
|
|
1582
|
-
* @throws If the password is not a valid string.
|
|
1583
|
-
*/
|
|
1584
|
-
function assertIsValidPassword(password) {
|
|
1585
|
-
if (typeof password !== 'string') {
|
|
1586
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.WrongPasswordType);
|
|
1587
|
-
}
|
|
1588
|
-
if (!password?.length) {
|
|
1589
|
-
throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidEmptyPassword);
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
1681
|
/**
|
|
1593
1682
|
* Lock the given mutex before executing the given function,
|
|
1594
1683
|
* and release it after the function is resolved or after an
|