@metamask-previews/seedless-onboarding-controller 12.0.0-preview-44b7ded21 → 12.0.0-preview-2750df1dc

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 CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Changed
11
+
12
+ - Replace JS AES implementation with `@metamask/cryptography` ([#10659](https://github.com/MetaMask/core/pull/10659))
13
+
10
14
  ## [12.0.0]
11
15
 
12
16
  ### Added
@@ -1 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.d.ts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SeedlessOnboardingController.d.ts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,KAAK,eAAe,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAE3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,kBAAkB,EAIlB,oBAAoB,EAErB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;AAWvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EACL,cAAc,EAEd,UAAU,EAEV,kCAAkC,EAEnC,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EACV,qCAAqC,EACrC,mCAAmC,EACpC,MAAM,yCAAyC,CAAC;AAKjD,OAAO,KAAK,EAEV,iCAAiC,EAEjC,qBAAqB,EAMtB,MAAM,YAAY,CAAC;AAuBpB,YAAY,EACV,mCAAmC,EACnC,kCAAkC,EAClC,0CAA0C,EAC1C,qCAAqC,EACrC,mCAAmC,EACnC,4CAA4C,GAC7C,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,uDAAuD,EAAE,MAAM,YAAY,CAAC;AAmCrF,qBAAa,4BAA4B,CACvC,aAAa,GAAG,eAAe,CAAC,aAAa,EAC7C,6BAA6B,GAAG,eAAe,CAAC,oBAAoB,EACpE,gBAAgB,SACd,0BAA0B,CAAC,6BAA6B,CAAC,GACzD,uBAAuB,CAAC,6BAA6B,CAAC,CACxD,SAAQ,cAAc,CACtB,OAAO,cAAc,EACrB,iCAAiC,EACjC,qCAAqC,CACtC;;IAkBC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IA2BxC;;;;;;;;;;;;;OAaG;IACH,YAAY,EACV,SAAS,EACT,KAAK,EACL,SAAS,EACT,eAAe,EACf,OAAiC,EACjC,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,wBAAyD,GAC1D,EAAE,mCAAmC,CACpC,aAAa,EACb,6BAA6B,EAC7B,gBAAgB,CACjB,EA0BA;IAEK,wBAAwB,IAAI,OAAO,CAAC;QACxC,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC,CAwBD;IAED;;;OAGG;IACG,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM7C;IAED;;;;;;;;;;;;;;;;;OAiBG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,uBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0D9B;IAED;;;;;;;OAOG;IACG,iCAAiC,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA4Df;IAED;;;;;;;;OAQG;IACG,gBAAgB,CACpB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,IAAI,CAAC,CAgCf;IAED;;;;;;;;;;;;OAYG;IACG,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CActC;IAED;;;;;;;OAOG;IACH,mBAAmB,CAAC,OAAO,EAAE,kCAAkC,GAAG,IAAI,CAErE;IA6ED;;;;;;;OAOG;IACG,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA0CrE;IAED;;;;;;;;OAQG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Df;IAED;;;;;;OAMG;IACH,yBAAyB,CACvB,UAAU,EACN,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,GAC5D,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,EAAE,GACjE,IAAI,CAIN;IAED;;;;;;;;OAQG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GACA,OAAO,CAAC,IAAI,CAAC,CAUf;IAED;;;;;;;;OAQG;IACH,wBAAwB,CACtB,IAAI,EAAE,UAAU,EAChB,IAAI,GAAE,UAAgC,GACrC,qBAAqB,GAAG,SAAS,CAKnC;IAED;;;;;;;;;;OAUG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCpD;IAED;;;;;;;;OAQG;IACG,gCAAgC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;IAED;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAY/B;IAED;;;;;;;;OAQG;IACG,wBAAwB,CAAC,EAC7B,cAAc,GACf,EAAE;QACD,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB;IAED;;;;;;;OAOG;IACG,oBAAoB,CAAC,EACzB,cAAc,EACd,iBAAqB,GACtB,EAAE;QACD,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB;IAoED;;;;;;;;;OASG;IACG,uBAAuB,CAAC,OAAO,CAAC,EAAE;QACtC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;KACzC,GAAG,OAAO,CAAC,OAAO,CAAC,CAkEnB;IAED;;;;;;;;;;OAUG;IACG,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO/C;IAuCD;;OAEG;IACH,UAAU,IAAI,IAAI,CAMjB;IAoDD;;;;;OAKG;IACG,yBAAyB,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;IAED;;;;;OAKG;IACG,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAIhD;IA8xBD;;;;;;;;;OASG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBvC;IAqJD;;;;;;;OAOG;IACG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2CxC;IAED;;;;;;OAMG;IACG,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC,CAqChD;IAED;;;;;;OAMG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQlD;IAgGD;;;;OAIG;IACI,yBAAyB,IAAI,OAAO,CAU1C;IAED;;;;;;OAMG;IACI,+BAA+B,IAAI,OAAO,CAUhD;IAED;;;;;;;OAOG;IACI,uBAAuB,IAAI,OAAO,CAYxC;CAqBF"}
@@ -1,10 +1,8 @@
1
1
  import { keccak256AndHexify } from '@metamask/auth-network-utils';
2
2
  import { BaseController } from '@metamask/base-controller';
3
+ import { decrypt, encrypt, IV_LENGTH } from '@metamask/cryptography/aes-gcm';
3
4
  import { ToprfSecureBackup, EncAccountDataType, } from '@metamask/toprf-secure-backup';
4
- import { base64ToBytes, bytesToBase64 } from '@metamask/utils';
5
- import { gcm } from '@noble/ciphers/aes';
6
- import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
7
- import { managedNonce } from '@noble/ciphers/webcrypto';
5
+ import { base64ToBytes, bytesToBase64, bytesToString, stringToBytes, concatBytes, } from '@metamask/utils';
8
6
  import { secp256k1 } from '@noble/curves/secp256k1';
9
7
  import { Mutex } from 'async-mutex';
10
8
  import { controllerName, PASSWORD_OUTDATED_CACHE_TTL_MS, SecretType, SeedlessOnboardingControllerErrorMessage, SeedlessOnboardingMigrationVersion, Web3AuthNetwork, } from './constants.js';
@@ -878,8 +876,8 @@ export class SeedlessOnboardingController extends BaseController {
878
876
  * @param keyringEncryptionKey - The keyring encryption key.
879
877
  */
880
878
  async #storeKeyringEncryptionKey(encKey, keyringEncryptionKey) {
881
- const aes = managedNonce(gcm)(encKey);
882
- const encryptedKeyringEncryptionKey = aes.encrypt(utf8ToBytes(keyringEncryptionKey));
879
+ const { ciphertext, iv } = await encrypt(encKey, stringToBytes(keyringEncryptionKey));
880
+ const encryptedKeyringEncryptionKey = concatBytes([iv, ciphertext]);
883
881
  this.update((state) => {
884
882
  state.encryptedKeyringEncryptionKey = bytesToBase64(encryptedKeyringEncryptionKey);
885
883
  });
@@ -894,9 +892,10 @@ export class SeedlessOnboardingController extends BaseController {
894
892
  const { encryptedKeyringEncryptionKey: encryptedKey } = this.state;
895
893
  assertIsEncryptedKeyringEncryptionKeySet(encryptedKey);
896
894
  const encryptedPasswordBytes = base64ToBytes(encryptedKey);
897
- const aes = managedNonce(gcm)(encKey);
898
- const password = aes.decrypt(encryptedPasswordBytes);
899
- return bytesToUtf8(password);
895
+ const iv = encryptedPasswordBytes.slice(0, IV_LENGTH);
896
+ const ciphertext = encryptedPasswordBytes.slice(IV_LENGTH);
897
+ const password = await decrypt(encKey, iv, ciphertext);
898
+ return bytesToString(password);
900
899
  }
901
900
  /**
902
901
  * Decrypt the seedless encryption key from state.
@@ -908,9 +907,10 @@ export class SeedlessOnboardingController extends BaseController {
908
907
  const { encryptedSeedlessEncryptionKey: encryptedKey } = this.state;
909
908
  assertIsEncryptedSeedlessEncryptionKeySet(encryptedKey);
910
909
  const encryptedKeyBytes = base64ToBytes(encryptedKey);
911
- const aes = managedNonce(gcm)(encKey);
912
- const seedlessEncryptionKey = aes.decrypt(encryptedKeyBytes);
913
- return bytesToUtf8(seedlessEncryptionKey);
910
+ const iv = encryptedKeyBytes.slice(0, IV_LENGTH);
911
+ const ciphertext = encryptedKeyBytes.slice(IV_LENGTH);
912
+ const seedlessEncryptionKey = await decrypt(encKey, iv, ciphertext);
913
+ return bytesToString(seedlessEncryptionKey);
914
914
  }
915
915
  /**
916
916
  * Recover the authentication public key from the state.
@@ -1282,7 +1282,7 @@ export class SeedlessOnboardingController extends BaseController {
1282
1282
  updatedState.vaultEncryptionSalt = JSON.parse(updatedEncVault).salt;
1283
1283
  // encrypt the seedless encryption key with the password encryption key from TOPRF network
1284
1284
  updatedState.encryptedSeedlessEncryptionKey =
1285
- this.#encryptSeedlessEncryptionKey(exportedKeyString, pwEncKey);
1285
+ await this.#encryptSeedlessEncryptionKey(exportedKeyString, pwEncKey);
1286
1286
  }
1287
1287
  else if (vaultEncryptionKey && vaultEncryptionSalt) {
1288
1288
  const encryptionKey = await this.#vaultEncryptor.importKey(vaultEncryptionKey);
@@ -1317,10 +1317,9 @@ export class SeedlessOnboardingController extends BaseController {
1317
1317
  * @param pwEncKey - The password encryption key from TOPRF network.
1318
1318
  * @returns The encrypted seedless encryption key.
1319
1319
  */
1320
- #encryptSeedlessEncryptionKey(vaultEncryptionKey, pwEncKey) {
1321
- const aes = managedNonce(gcm)(pwEncKey);
1322
- const encryptedKey = aes.encrypt(utf8ToBytes(vaultEncryptionKey));
1323
- return bytesToBase64(encryptedKey);
1320
+ async #encryptSeedlessEncryptionKey(vaultEncryptionKey, pwEncKey) {
1321
+ const { ciphertext, iv } = await encrypt(pwEncKey, stringToBytes(vaultEncryptionKey));
1322
+ return bytesToBase64(concatBytes([iv, ciphertext]));
1324
1323
  }
1325
1324
  /**
1326
1325
  * Get the access token and revoke token from the state or the vault.
@@ -1 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.js","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport { BaseController } from '@metamask/base-controller';\nimport type * as encryptionUtils from '@metamask/browser-passworder';\nimport type {\n DefaultEncryptionResult,\n EncryptionResultConstraint,\n Encryptor,\n} from '@metamask/keyring-controller';\nimport type {\n AuthenticateResult,\n ChangeEncryptionKeyResult,\n KeyPair,\n RecoverEncryptionKeyResult,\n SEC1EncodedPublicKey,\n FetchedSecretDataItem,\n} from '@metamask/toprf-secure-backup';\nimport {\n ToprfSecureBackup,\n EncAccountDataType,\n} from '@metamask/toprf-secure-backup';\nimport { base64ToBytes, bytesToBase64 } from '@metamask/utils';\nimport { gcm } from '@noble/ciphers/aes';\nimport { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';\nimport { managedNonce } from '@noble/ciphers/webcrypto';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { Mutex } from 'async-mutex';\n\nimport type { AuthConnection } from './constants.js';\nimport {\n controllerName,\n PASSWORD_OUTDATED_CACHE_TTL_MS,\n SecretType,\n SeedlessOnboardingControllerErrorMessage,\n SeedlessOnboardingMigrationVersion,\n Web3AuthNetwork,\n} from './constants.js';\nimport {\n PasswordSyncError,\n RecoveryError,\n SeedlessOnboardingError,\n} from './errors.js';\nimport { projectLogger, createModuleLogger } from './logger.js';\nimport { SecretMetadata } from './SecretMetadata.js';\nimport type {\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n} from './SeedlessOnboardingController-types.js';\nimport {\n getInitialSeedlessOnboardingControllerStateWithDefaults,\n seedlessOnboardingMetadata,\n} from './state.js';\nimport type {\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerState,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n RefreshJWTToken,\n RevokeRefreshToken,\n RenewRefreshToken,\n VaultData,\n DeserializedVaultData,\n} from './types.js';\nimport {\n assertIsEncryptedKeyringEncryptionKeySet,\n assertIsEncryptedSeedlessEncryptionKeySet,\n assertIsPasswordOutdatedCacheValid,\n assertIsSeedlessOnboardingUserAuthenticated,\n assertIsValidPassword,\n compareAndGetLatestToken,\n decodeJWTToken,\n decodeNodeAuthToken,\n deserializeVaultData,\n getDataTypeMigrationUpdates,\n getNewSocialBackupsMetadata,\n trackIncompleteMetadataBackupEvents,\n isAuthTokenError,\n isMaxKeyChainLengthError,\n isTokenNearExpiry,\n parseVaultData,\n parseAndValidateSecretMetadataBackup,\n serializeVaultData,\n} from './utils/index.js';\nimport type { SecretBackupData } from './utils/index.js';\n\nexport type {\n SeedlessOnboardingControllerActions,\n SeedlessOnboardingControllerEvents,\n SeedlessOnboardingControllerGetStateAction,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerStateChangeEvent,\n} from './SeedlessOnboardingController-types.js';\nexport { getInitialSeedlessOnboardingControllerStateWithDefaults } from './state.js';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'fetchMetadataAccessCreds',\n 'preloadToprfNodeDetails',\n 'authenticate',\n 'createToprfKeyAndBackupSeedPhrase',\n 'addNewSecretData',\n 'fetchAllSecretData',\n 'changePassword',\n 'updateBackupMetadataState',\n 'verifyVaultPassword',\n 'getSecretDataBackupState',\n 'submitPassword',\n 'identifyIncompleteMetadataBackup',\n 'setLocked',\n 'syncLatestGlobalPassword',\n 'submitGlobalPassword',\n 'checkIsPasswordOutdated',\n 'getIsUserAuthenticated',\n 'clearState',\n 'storeKeyringEncryptionKey',\n 'loadKeyringEncryptionKey',\n 'refreshAuthTokens',\n 'revokePendingRefreshTokens',\n 'rotateRefreshToken',\n 'getAccessToken',\n 'checkNodeAuthTokenExpired',\n 'checkMetadataAccessTokenExpired',\n 'checkAccessTokenExpired',\n 'runMigrations',\n] as const;\n\nexport class SeedlessOnboardingController<\n EncryptionKey = encryptionUtils.EncryptionKey,\n SupportedKeyDerivationOptions = encryptionUtils.KeyDerivationOptions,\n EncryptionResult extends\n EncryptionResultConstraint<SupportedKeyDerivationOptions> =\n DefaultEncryptionResult<SupportedKeyDerivationOptions>,\n> extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: Encryptor<\n EncryptionKey,\n SupportedKeyDerivationOptions,\n EncryptionResult\n >;\n\n readonly #controllerOperationMutex = new Mutex();\n\n readonly #vaultOperationMutex = new Mutex();\n\n /**\n * In-flight promise for `refreshAuthTokens`. Any concurrent caller that\n * arrives while a refresh is already in-progress will share this promise\n * rather than issuing a second HTTP request with the same refresh token.\n */\n #pendingRefreshPromise: Promise<void> | undefined;\n\n readonly toprfClient: ToprfSecureBackup;\n\n readonly #refreshJWTToken: RefreshJWTToken;\n\n readonly #revokeRefreshToken: RevokeRefreshToken;\n\n readonly #renewRefreshToken: RenewRefreshToken;\n\n /**\n * The TTL of the password outdated cache in milliseconds.\n */\n readonly #passwordOutdatedCacheTTL: number;\n\n /**\n * Controller lock state.\n *\n * The controller lock is synchronized with the keyring lock.\n */\n #isUnlocked = false;\n\n /**\n * Cached decrypted vault data.\n *\n * This is used to cache the decrypted vault data to avoid decrypting the vault data multiple times.\n */\n #cachedDecryptedVaultData: DeserializedVaultData | undefined;\n\n /**\n * Creates a new SeedlessOnboardingController instance.\n *\n * @param options - The options for the SeedlessOnboardingController.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.encryptor - An optional encryptor to use for encrypting and decrypting seedless onboarding vault.\n * @param options.toprfKeyDeriver - An optional key derivation interface for the TOPRF client.\n * @param options.network - The network to be used for the Seedless Onboarding flow.\n * @param options.refreshJWTToken - A function to get a new jwt token using refresh token.\n * @param options.revokeRefreshToken - A function to revoke the refresh token.\n * @param options.renewRefreshToken - A function to renew the refresh token and get new revoke token.\n * @param options.passwordOutdatedCacheTTL - The TTL of the password outdated cache in milliseconds.,\n */\n constructor({\n messenger,\n state,\n encryptor,\n toprfKeyDeriver,\n network = Web3AuthNetwork.Mainnet,\n refreshJWTToken,\n revokeRefreshToken,\n renewRefreshToken,\n passwordOutdatedCacheTTL = PASSWORD_OUTDATED_CACHE_TTL_MS,\n }: SeedlessOnboardingControllerOptions<\n EncryptionKey,\n SupportedKeyDerivationOptions,\n EncryptionResult\n >) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: getInitialSeedlessOnboardingControllerStateWithDefaults(state),\n messenger,\n });\n\n assertIsPasswordOutdatedCacheValid(passwordOutdatedCacheTTL);\n this.#passwordOutdatedCacheTTL = passwordOutdatedCacheTTL;\n\n this.#vaultEncryptor = encryptor;\n\n this.toprfClient = new ToprfSecureBackup({\n network,\n keyDeriver: toprfKeyDeriver,\n fetchMetadataAccessCreds: this.fetchMetadataAccessCreds.bind(this),\n });\n this.#refreshJWTToken = refreshJWTToken;\n this.#revokeRefreshToken = revokeRefreshToken;\n this.#renewRefreshToken = renewRefreshToken;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n async fetchMetadataAccessCreds(): Promise<{\n metadataAccessToken: string;\n }> {\n const { metadataAccessToken } = this.state;\n if (!metadataAccessToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidMetadataAccessToken,\n );\n }\n\n // Use the same 90%-lifetime threshold as checkMetadataAccessTokenExpired\n // so both code paths agree on when a refresh is needed.\n const decodedToken = decodeJWTToken(metadataAccessToken);\n if (isTokenNearExpiry(decodedToken.exp, decodedToken.iat)) {\n // Token is near expiry or already expired, refresh it\n await this.refreshAuthTokens();\n\n // Get the new token after refresh\n const { metadataAccessToken: newMetadataAccessToken } = this.state;\n\n return {\n metadataAccessToken: newMetadataAccessToken as string,\n };\n }\n\n return { metadataAccessToken };\n }\n\n /**\n * Gets the node details for the TOPRF operations.\n * This function can be called to get the node endpoints, indexes and pubkeys and cache them locally.\n */\n async preloadToprfNodeDetails(): Promise<void> {\n try {\n await this.toprfClient.getNodeDetails();\n } catch {\n log('Failed to fetch node details');\n }\n }\n\n /**\n * Authenticate OAuth user using the seedless onboarding flow\n * and determine if the user is already registered or not.\n *\n * @param params - The parameters for authenticate OAuth user.\n * @param params.idTokens - The ID token(s) issued by OAuth verification service. Currently this array only contains a single idToken which is verified by all the nodes, in future we are considering to issue a unique idToken for each node.\n * @param params.authConnection - The social login provider.\n * @param params.authConnectionId - OAuth authConnectionId from dashboard\n * @param params.userId - user email or id from Social login\n * @param params.groupedAuthConnectionId - Optional grouped authConnectionId to be used for the authenticate request.\n * @param params.socialLoginEmail - The user email from Social login.\n * @param params.refreshToken - Refresh token issued during OAuth login. Written to state when provided.\n * @param params.revokeToken - revoke token for revoking refresh token and get new refresh token and new revoke token.\n * @param params.accessToken - Access token for pairing with profile sync auth service and to access other services.\n * @param params.metadataAccessToken - Metadata access token for accessing the metadata service before the vault is created or unlocked.\n * @param params.skipLock - Optional flag to skip acquiring the controller lock. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n refreshToken: string;\n revokeToken?: string;\n skipLock?: boolean;\n }): Promise<AuthenticateResult> {\n const doAuthenticateWithNodes = async (): Promise<AuthenticateResult> => {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n refreshToken,\n revokeToken,\n accessToken,\n metadataAccessToken,\n } = params;\n\n const authenticationResult = await this.toprfClient.authenticate({\n authConnectionId,\n userId,\n idTokens,\n groupedAuthConnectionId,\n });\n // update the state with the authenticated user info\n this.update((state) => {\n state.nodeAuthTokens = authenticationResult.nodeAuthTokens;\n state.authConnectionId = authConnectionId;\n state.groupedAuthConnectionId = groupedAuthConnectionId;\n state.userId = userId;\n state.authConnection = authConnection;\n state.socialLoginEmail = socialLoginEmail;\n state.metadataAccessToken = metadataAccessToken;\n state.refreshToken = refreshToken;\n if (revokeToken) {\n // Temporarily store revoke token & access token in state for later vault creation\n state.revokeToken = revokeToken;\n }\n state.accessToken = accessToken;\n\n // we will check if the controller state is properly set with the authenticated user info\n // before setting the isSeedlessOnboardingUserAuthenticated to true\n assertIsSeedlessOnboardingUserAuthenticated(state);\n state.isSeedlessOnboardingUserAuthenticated = true;\n });\n\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n };\n return params.skipLock\n ? await doAuthenticateWithNodes()\n : await this.#withControllerLock(doAuthenticateWithNodes);\n }\n\n /**\n * Create a new TOPRF encryption key using given password and backups the provided seed phrase.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @param seedPhrase - The initial seed phrase (Mnemonic) created together with the wallet.\n * @param keyringId - The keyring id of the backup seed phrase\n * @returns A promise that resolves to the encrypted seed phrase and the encryption key.\n */\n async createToprfKeyAndBackupSeedPhrase(\n password: string,\n seedPhrase: Uint8Array,\n keyringId: string,\n ): Promise<void> {\n return await this.#withControllerLock(async () => {\n // to make sure that fail fast,\n // assert that the user is authenticated before creating the TOPRF key and backing up the seed phrase\n this.#assertIsAuthenticatedUser(this.state);\n\n if (this.state.vault) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.VaultAlreadyExists,\n );\n }\n\n // locally evaluate the encryption key from the password\n const { encKey, pwEncKey, authKeyPair, oprfKey } =\n await this.toprfClient.createLocalKey({\n password,\n });\n const performKeyCreationAndBackup = async (): Promise<void> => {\n // encrypt and store the secret data\n const secretMetadata = await this.#encryptAndStoreSecretData({\n data: seedPhrase,\n dataType: EncAccountDataType.PrimarySrp,\n encKey,\n authKeyPair,\n options: {\n keyringId,\n },\n // Persist local backup state only after the full operation succeeds.\n skipStatePersist: true,\n });\n\n // store/persist the encryption key shares\n // We store the secret metadata in the metadata store first. If this operation fails,\n // we avoid persisting the encryption key shares to prevent a situation where a user appears\n // to have an account but with no associated data.\n await this.#persistOprfKey(oprfKey, authKeyPair.pk);\n // create a new vault with the resulting authentication data\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfPwEncryptionKey: pwEncKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n\n // Mark migration as complete since this new backup was created with the new data format (dataType)\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n\n // Persist local backup state after all operations succeed.\n this.#filterDupesAndUpdateSocialBackupsMetadata({\n keyringId,\n data: seedPhrase,\n type: secretMetadata.type,\n });\n };\n\n await this.#executeWithTokenRefresh(\n performKeyCreationAndBackup,\n 'createToprfKeyAndBackupSeedPhrase',\n );\n });\n }\n\n /**\n * Encrypt and add a new secret data to the metadata store.\n *\n * @param data - The data to add.\n * @param dataType - The data type classification for the secret data.\n * @param options - Optional options object, which includes optional data to be added to the metadata store.\n * @param options.keyringId - The keyring id of the backup keyring (SRP).\n * @returns A promise that resolves to the success of the operation.\n */\n async addNewSecretData(\n data: Uint8Array,\n dataType: EncAccountDataType,\n options?: {\n keyringId?: string;\n },\n ): Promise<void> {\n if (dataType === EncAccountDataType.PrimarySrp) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.PrimarySrpCannotBeAddedViaAddNewSecretData,\n );\n }\n\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n\n const performBackup = async (): Promise<void> => {\n await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n\n // verify the password and unlock the vault\n const { toprfEncryptionKey, toprfAuthKeyPair } =\n await this.#unlockVaultAndGetVaultData();\n\n // encrypt and store the secret data\n await this.#encryptAndStoreSecretData({\n data,\n dataType,\n encKey: toprfEncryptionKey,\n authKeyPair: toprfAuthKeyPair,\n options,\n });\n };\n\n await this.#executeWithTokenRefresh(performBackup, 'addNewSecretData');\n });\n }\n\n /**\n * Run any pending seedless onboarding migrations.\n *\n * This method should be called by clients after the controller is unlocked\n * to ensure legacy data is migrated to the latest format.\n *\n * Migrations are idempotent - running this multiple times is safe.\n * The migration version is tracked in state to prevent re-running migrations.\n *\n * @returns A promise that resolves to `true` if data was actually migrated\n * (items were updated on the server), `false` otherwise.\n * @throws If the password is outdated (changed on another device).\n */\n async runMigrations(): Promise<boolean> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n\n await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n\n if (this.state.migrationVersion < SeedlessOnboardingMigrationVersion.V1) {\n return this.#migrateDataTypes();\n }\n return false;\n });\n }\n\n /**\n * Set the migration version directly.\n *\n * Use this for new users who don't have legacy data to migrate,\n * avoiding an unnecessary API call from `runMigrations()`.\n *\n * @param version - The migration version to set.\n */\n setMigrationVersion(version: SeedlessOnboardingMigrationVersion): void {\n this.#setMigrationVersion(version);\n }\n\n /**\n * Assigns dataType (PrimarySrp/ImportedSrp/ImportedPrivateKey) to legacy secrets\n * that were created before the dataType field was introduced.\n *\n * This migration:\n * 1. Fetches all secret data items\n * 2. Identifies items that need migration (version !== 'v2' OR dataType not set)\n * 3. Assigns PrimarySrp to the first mnemonic (by timestamp)\n * 4. Assigns ImportedSrp to subsequent mnemonics\n * 5. Assigns ImportedPrivateKey to private keys\n * 6. Updates the items via SDK (which sets version to 'v2' and dataType)\n * 7. Updates the migration version in state\n *\n * Note: The SDK's updateSecretDataItem automatically sets version to 'v2'\n * when updating dataType, ensuring migrated items are marked as v2.\n *\n * @returns A promise that resolves to `true` if items were actually updated\n * on the server, `false` if no items needed migration.\n */\n async #migrateDataTypes(): Promise<boolean> {\n return await this.#executeWithTokenRefresh(async () => {\n const { toprfEncryptionKey, toprfAuthKeyPair } =\n await this.#unlockVaultAndGetVaultData();\n\n let secretDatas: SecretMetadata[];\n try {\n secretDatas = await this.#fetchAllSecretDataFromMetadataStore(\n toprfEncryptionKey,\n toprfAuthKeyPair,\n );\n } catch (error) {\n // If no secret data found, just update migration version\n if (\n error instanceof Error &&\n error.message ===\n SeedlessOnboardingControllerErrorMessage.NoSecretDataFound\n ) {\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n return false;\n }\n throw error;\n }\n\n const updates = getDataTypeMigrationUpdates(secretDatas);\n\n if (updates.length === 1) {\n await this.toprfClient.updateSecretDataItem({\n itemId: updates[0].itemId,\n dataType: updates[0].dataType,\n authKeyPair: toprfAuthKeyPair,\n });\n } else if (updates.length > 1) {\n await this.toprfClient.batchUpdateSecretDataItems({\n updateItems: updates,\n authKeyPair: toprfAuthKeyPair,\n });\n }\n\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n\n return updates.length > 0;\n }, 'migrateDataTypes');\n }\n\n /**\n * Set the migration version in state.\n *\n * @param version - The migration version to set.\n */\n #setMigrationVersion(version: number): void {\n this.update((state) => {\n state.migrationVersion = version;\n });\n }\n\n /**\n * Fetches all secret data items from the metadata store.\n *\n * Decrypts the secret data and returns the decrypted secret data using the recovered encryption key from the password.\n *\n * @param password - The optional password used to create new wallet. If not provided, `cached Encryption Key` will be used.\n * @returns A promise that resolves to the secret metadata items.\n */\n async fetchAllSecretData(password?: string): Promise<SecretMetadata[]> {\n return await this.#withControllerLock(async () => {\n return await this.#executeWithTokenRefresh(async () => {\n // assert that the user is authenticated before fetching the secret data\n this.#assertIsAuthenticatedUser(this.state);\n\n let encKey: Uint8Array;\n let pwEncKey: Uint8Array;\n let authKeyPair: KeyPair;\n\n if (password) {\n const recoverEncKeyResult = await this.#recoverEncKey(password);\n encKey = recoverEncKeyResult.encKey;\n pwEncKey = recoverEncKeyResult.pwEncKey;\n authKeyPair = recoverEncKeyResult.authKeyPair;\n } else {\n this.#assertIsUnlocked();\n // verify the password and unlock the vault\n const keysFromVault = await this.#unlockVaultAndGetVaultData();\n encKey = keysFromVault.toprfEncryptionKey;\n pwEncKey = keysFromVault.toprfPwEncryptionKey;\n authKeyPair = keysFromVault.toprfAuthKeyPair;\n }\n\n const secrets = await this.#fetchAllSecretDataFromMetadataStore(\n encKey,\n authKeyPair,\n );\n\n if (password) {\n // if password is provided, we need to create a new vault with the auth data. (supposedly the user is trying to rehydrate the wallet)\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfPwEncryptionKey: pwEncKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return secrets;\n }, 'fetchAllSecretData');\n });\n }\n\n /**\n * Update the password of the seedless onboarding flow.\n *\n * Changing password will also update the encryption key, metadata store and the vault with new encrypted values.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to the success of the operation.\n */\n async changePassword(\n newPassword: string,\n oldPassword: string,\n ): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n // verify the old password of the encrypted vault\n await this.verifyVaultPassword(oldPassword, {\n skipLock: true, // skip lock since we already have the lock\n });\n\n const attemptChangePassword = async (): Promise<void> => {\n const { latestKeyIndex } = await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n // load keyring encryption key if it exists\n let keyringEncryptionKey: string | undefined;\n if (this.state.encryptedKeyringEncryptionKey) {\n keyringEncryptionKey = await this.loadKeyringEncryptionKey();\n }\n\n // update the encryption key with new password and update the Metadata Store\n const {\n encKey: newEncKey,\n pwEncKey: newPwEncKey,\n authKeyPair: newAuthKeyPair,\n } = await this.#changeEncryptionKey({\n oldPassword,\n newPassword,\n latestKeyIndex,\n });\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey,\n rawToprfPwEncryptionKey: newPwEncKey,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n\n this.#resetPasswordOutdatedCache();\n\n // store the keyring encryption key if it exists\n if (keyringEncryptionKey) {\n await this.storeKeyringEncryptionKey(keyringEncryptionKey);\n }\n };\n\n try {\n await this.#executeWithTokenRefresh(\n attemptChangePassword,\n 'changePassword',\n );\n } catch (error) {\n log('Error changing password', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToChangePassword,\n {\n cause: error,\n },\n );\n }\n });\n }\n\n /**\n * Update the backup metadata state for the given secret data.\n *\n * @param secretData - The data to backup, can be a single backup or array of backups.\n * @param secretData.keyringId - The keyring id associated with the backup secret data.\n * @param secretData.data - The secret data to update the backup metadata state.\n */\n updateBackupMetadataState(\n secretData:\n | (Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array })\n | (Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array })[],\n ): void {\n this.#assertIsUnlocked();\n\n this.#filterDupesAndUpdateSocialBackupsMetadata(secretData);\n }\n\n /**\n * Verify the password validity by decrypting the vault.\n *\n * @param password - The password to verify.\n * @param options - Optional options object.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to the success of the operation.\n * @throws {Error} If the password is invalid or the vault is not initialized.\n */\n async verifyVaultPassword(\n password: string,\n options?: {\n skipLock?: boolean;\n },\n ): Promise<void> {\n const doVerify = async (): Promise<void> => {\n if (!this.state.vault) {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultError);\n }\n await this.#vaultEncryptor.decrypt(password, this.state.vault);\n };\n return options?.skipLock\n ? await doVerify()\n : await this.#withControllerLock(doVerify);\n }\n\n /**\n * Get backup state of the given secret data, from the controller state.\n *\n * If the given secret data is not backed up and not found in the state, it will return `undefined`.\n *\n * @param data - The data to get the backup state of.\n * @param type - The type of the secret data.\n * @returns The backup state of the given secret data.\n */\n getSecretDataBackupState(\n data: Uint8Array,\n type: SecretType = SecretType.Mnemonic,\n ): SocialBackupsMetadata | undefined {\n const secretDataHash = keccak256AndHexify(data);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === secretDataHash && backup.type === type,\n );\n }\n\n /**\n * Submit the password to the controller, verify the password validity and unlock the controller.\n *\n * This method will be used especially when user unlock the wallet.\n * The provided password will be verified against the encrypted vault, encryption key will be derived and saved in the controller state.\n *\n * This operation is useful when user performs some actions that requires the user password/encryption key. e.g. add new srp backup\n *\n * @param password - The password to submit.\n * @returns A promise that resolves to the success of the operation.\n */\n async submitPassword(password: string): Promise<void> {\n return await this.#withControllerLock(async () => {\n // get the access token from the state before unlocking, it might be the new token set from the `refreshAuthTokens` method.\n const { accessToken: accessTokenBeforeUnlock } = this.state;\n\n const deserializedVaultData = await this.#unlockVaultAndGetVaultData({\n password,\n });\n\n const accessTokenFromDecryptedVault = deserializedVaultData.accessToken;\n\n // Pick the latest access token - the token from state might be newer (from refreshAuthTokens)\n // than the token stored in the vault.\n const latestAccessToken = this.#pickLatestAccessToken(\n accessTokenBeforeUnlock,\n accessTokenFromDecryptedVault,\n );\n\n // update the state and vault with the latest access token `ONLY` if it's different from the current access token in the state.\n if (latestAccessToken !== accessTokenFromDecryptedVault) {\n const updatedVaultData = {\n ...deserializedVaultData,\n accessToken: latestAccessToken,\n };\n\n await this.#updateVault({\n password,\n vaultData: updatedVaultData,\n pwEncKey: deserializedVaultData.toprfPwEncryptionKey,\n });\n }\n\n this.#setUnlocked();\n\n this.#identifyIncompleteMetadataBackup(password);\n });\n }\n\n /**\n * Identify an incomplete or mismatched primary SRP backup.\n *\n * This method must only be called after the controller has been unlocked.\n *\n * @param password - The password used to export the local primary SRP.\n * @returns A promise that resolves after identification and telemetry have\n * completed.\n */\n async identifyIncompleteMetadataBackup(password: string): Promise<void> {\n this.#assertIsUnlocked();\n\n await this.#identifyIncompleteMetadataBackup(password);\n }\n\n /**\n * Set the controller to locked state, and deallocate the secrets (vault encryption key and salt).\n *\n * When the controller is locked, the user will not be able to perform any operations on the controller/vault.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async setLocked(): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.update((state) => {\n delete state.vaultEncryptionKey;\n delete state.vaultEncryptionSalt;\n delete state.revokeToken;\n delete state.accessToken;\n });\n\n this.#cachedDecryptedVaultData = undefined;\n this.#isUnlocked = false;\n });\n }\n\n /**\n * Sync the latest global password to the controller.\n * reset vault with latest globalPassword,\n * persist the latest global password authPubKey\n *\n * @param params - The parameters for syncing the latest global password.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the success of the operation.\n */\n async syncLatestGlobalPassword({\n globalPassword,\n }: {\n globalPassword: string;\n }): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n const doSyncPassword = async (): Promise<void> => {\n // update vault with latest globalPassword\n const { encKey, pwEncKey, authKeyPair } =\n await this.#recoverEncKey(globalPassword);\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: globalPassword,\n rawToprfEncryptionKey: encKey,\n rawToprfPwEncryptionKey: pwEncKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n\n this.#resetPasswordOutdatedCache();\n };\n return await this.#executeWithTokenRefresh(\n doSyncPassword,\n 'syncLatestGlobalPassword',\n );\n });\n }\n\n /**\n * @description Unlock the controller with the latest global password.\n *\n * @param params - The parameters for unlocking the controller.\n * @param params.maxKeyChainLength - The maximum chain length of the pwd encryption keys.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the success of the operation.\n */\n async submitGlobalPassword({\n globalPassword,\n maxKeyChainLength = 5,\n }: {\n globalPassword: string;\n maxKeyChainLength?: number;\n }): Promise<void> {\n return await this.#withControllerLock(async () => {\n return await this.#executeWithTokenRefresh(async () => {\n const currentDeviceAuthPubKey = this.#recoverAuthPubKey();\n await this.#submitGlobalPassword({\n targetAuthPubKey: currentDeviceAuthPubKey,\n globalPassword,\n maxKeyChainLength,\n });\n }, 'submitGlobalPassword');\n });\n }\n\n /**\n * @description Submit the global password to the controller, verify the\n * password validity and unlock the controller.\n *\n * @param params - The parameters for submitting the global password.\n * @param params.maxKeyChainLength - The maximum chain length of the pwd encryption keys.\n * @param params.targetAuthPubKey - The target public key of the keyring\n * encryption key to recover.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the keyring encryption key\n * corresponding to the current authPubKey in state.\n */\n async #submitGlobalPassword({\n targetAuthPubKey,\n globalPassword,\n maxKeyChainLength,\n }: {\n targetAuthPubKey: SEC1EncodedPublicKey;\n globalPassword: string;\n maxKeyChainLength: number;\n }): Promise<void> {\n const { pwEncKey: globalPwEncKey, authKeyPair: globalAuthKeyPair } =\n await this.#recoverEncKey(globalPassword);\n\n try {\n // Recover vault encryption key.\n const res = await this.toprfClient.recoverPwEncKey({\n targetAuthPubKey,\n curPwEncKey: globalPwEncKey,\n curAuthKeyPair: globalAuthKeyPair,\n maxPwChainLength: maxKeyChainLength,\n });\n const { pwEncKey } = res;\n const vaultKey = await this.#loadSeedlessEncryptionKey(pwEncKey);\n\n // accessToken before unlocking vault and flooding the state with values from the decrypted vault\n // it might be the new token set from the `refreshAuthTokens` method.\n const { accessToken: accessTokenBeforeUnlock } = this.state;\n\n // Unlock the controller\n const decryptedVaultData = await this.#unlockVaultAndGetVaultData({\n encryptionKey: vaultKey,\n });\n this.#setUnlocked();\n\n // Pick the latest access token - the token from state might be newer (from refreshAuthTokens)\n // than the token stored in the vault. The vault will be updated later by syncLatestGlobalPassword.\n this.#pickLatestAccessToken(\n accessTokenBeforeUnlock,\n decryptedVaultData.accessToken,\n );\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n if (isMaxKeyChainLengthError(error)) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MaxKeyChainLengthExceeded,\n );\n }\n throw PasswordSyncError.getInstance(error);\n }\n }\n\n /**\n * @description Check if the current password is outdated compare to the global password.\n *\n * @param options - Optional options object.\n * @param options.globalAuthPubKey - The global auth public key to compare with the current auth public key.\n * If not provided, the global auth public key will be fetched from the backend.\n * @param options.skipCache - If true, bypass the cache and force a fresh check.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to true if the password is outdated, false otherwise.\n */\n async checkIsPasswordOutdated(options?: {\n skipCache?: boolean;\n skipLock?: boolean;\n globalAuthPubKey?: SEC1EncodedPublicKey;\n }): Promise<boolean> {\n const doCheckIsPasswordExpired = async (): Promise<boolean> => {\n // cache result to reduce load on infra\n // Check cache first unless skipCache is true\n if (!options?.skipCache) {\n const { passwordOutdatedCache } = this.state;\n const now = Date.now();\n const isCacheValid =\n passwordOutdatedCache &&\n now - passwordOutdatedCache.timestamp <\n this.#passwordOutdatedCacheTTL;\n\n if (isCacheValid) {\n return passwordOutdatedCache.isExpiredPwd;\n }\n }\n\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n const currentDeviceAuthPubKey = this.#recoverAuthPubKey();\n\n let globalAuthPubKey = options?.globalAuthPubKey;\n if (!globalAuthPubKey) {\n const { authPubKey } = await this.toprfClient\n .fetchAuthPubKey({\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n })\n .catch((error) => {\n log('Error fetching auth pub key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchAuthPubKey,\n {\n cause: error,\n },\n );\n });\n globalAuthPubKey = authPubKey;\n }\n\n // use noble lib to deserialize and compare curve point\n const isExpiredPwd = !secp256k1.ProjectivePoint.fromHex(\n currentDeviceAuthPubKey,\n ).equals(secp256k1.ProjectivePoint.fromHex(globalAuthPubKey));\n // Cache the result in state\n this.update((state) => {\n state.passwordOutdatedCache = { isExpiredPwd, timestamp: Date.now() };\n });\n return isExpiredPwd;\n };\n\n return await this.#executeWithTokenRefresh(\n async () =>\n options?.skipLock\n ? await doCheckIsPasswordExpired()\n : await this.#withControllerLock(doCheckIsPasswordExpired),\n 'checkIsPasswordOutdated',\n );\n }\n\n /**\n * Check if the user is authenticated with the seedless onboarding flow by checking the token values in the state.\n *\n * This method will check the `accessToken` and `revokeToken` in the state, besides the social login authentication details.\n * If both are present, the user is authenticated.\n * If either is missing, the user is not authenticated.\n *\n * This method is useful when we want to check if the state has valid authenticated user details to perform vault creations.\n *\n * @returns True if the user is authenticated, false otherwise.\n */\n async getIsUserAuthenticated(): Promise<boolean> {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n return Boolean(this.state.accessToken) && Boolean(this.state.revokeToken);\n } catch {\n return false;\n }\n }\n\n #setUnlocked(): void {\n this.#isUnlocked = true;\n }\n\n /**\n * Compares two access tokens and picks the latest one based on JWT expiration.\n * If the tokens are different, the state is updated with the latest token.\n *\n * @param tokenBeforeUnlock - The access token from state before unlocking (may have been set by refreshAuthTokens).\n * @param tokenAfterUnlock - The access token from the decrypted vault after unlocking.\n * @returns The latest access token, or the token after unlock if no reconciliation was needed.\n */\n #pickLatestAccessToken(\n tokenBeforeUnlock: string | undefined,\n tokenAfterUnlock: string,\n ): string {\n let latestToken = tokenAfterUnlock;\n\n if (\n tokenBeforeUnlock &&\n tokenAfterUnlock &&\n tokenBeforeUnlock !== tokenAfterUnlock\n ) {\n latestToken = compareAndGetLatestToken(\n tokenBeforeUnlock,\n tokenAfterUnlock,\n );\n\n // Update the access token in the state with the latest access token\n this.update((state) => {\n state.accessToken = latestToken;\n });\n }\n\n return latestToken;\n }\n\n /**\n * Clears the current state of the SeedlessOnboardingController.\n */\n clearState(): void {\n const defaultState =\n getInitialSeedlessOnboardingControllerStateWithDefaults();\n this.update(() => {\n return defaultState;\n });\n }\n\n /**\n * Persist the encryption key for the seedless onboarding flow.\n *\n * @param oprfKey - The OPRF key to be splited and persisted.\n * @param authPubKey - The authentication public key.\n * @returns A promise that resolves to the success of the operation.\n */\n async #persistOprfKey(\n oprfKey: bigint,\n authPubKey: SEC1EncodedPublicKey,\n ): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n const { authConnectionId, groupedAuthConnectionId, userId } = this.state;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n log('Error persisting local encryption key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToPersistOprfKey,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Persist the authentication public key for the seedless onboarding flow.\n * convert to suitable format before persisting.\n *\n * @param params - The parameters for persisting the authentication public key.\n * @param params.authPubKey - The authentication public key to be persisted.\n */\n #persistAuthPubKey(params: { authPubKey: SEC1EncodedPublicKey }): void {\n this.update((state) => {\n state.authPubKey = bytesToBase64(params.authPubKey);\n });\n }\n\n /**\n * Store the keyring encryption key in state, encrypted under the current\n * encryption key.\n *\n * @param keyringEncryptionKey - The keyring encryption key.\n */\n async storeKeyringEncryptionKey(keyringEncryptionKey: string): Promise<void> {\n const { toprfPwEncryptionKey: encKey } =\n await this.#unlockVaultAndGetVaultData();\n await this.#storeKeyringEncryptionKey(encKey, keyringEncryptionKey);\n }\n\n /**\n * Load the keyring encryption key from state, decrypted under the current\n * encryption key.\n *\n * @returns The keyring encryption key.\n */\n async loadKeyringEncryptionKey(): Promise<string> {\n const { toprfPwEncryptionKey: encKey } =\n await this.#unlockVaultAndGetVaultData();\n return await this.#loadKeyringEncryptionKey(encKey);\n }\n\n /**\n * Encrypt the keyring encryption key and store it in state.\n *\n * @param encKey - The encryption key.\n * @param keyringEncryptionKey - The keyring encryption key.\n */\n async #storeKeyringEncryptionKey(\n encKey: Uint8Array,\n keyringEncryptionKey: string,\n ): Promise<void> {\n const aes = managedNonce(gcm)(encKey);\n const encryptedKeyringEncryptionKey = aes.encrypt(\n utf8ToBytes(keyringEncryptionKey),\n );\n this.update((state) => {\n state.encryptedKeyringEncryptionKey = bytesToBase64(\n encryptedKeyringEncryptionKey,\n );\n });\n }\n\n /**\n * Decrypt the keyring encryption key from state.\n *\n * @param encKey - The encryption key.\n * @returns The keyring encryption key.\n */\n async #loadKeyringEncryptionKey(encKey: Uint8Array): Promise<string> {\n const { encryptedKeyringEncryptionKey: encryptedKey } = this.state;\n assertIsEncryptedKeyringEncryptionKeySet(encryptedKey);\n const encryptedPasswordBytes = base64ToBytes(encryptedKey);\n const aes = managedNonce(gcm)(encKey);\n const password = aes.decrypt(encryptedPasswordBytes);\n return bytesToUtf8(password);\n }\n\n /**\n * Decrypt the seedless encryption key from state.\n *\n * @param encKey - The encryption key.\n * @returns The seedless encryption key.\n */\n async #loadSeedlessEncryptionKey(encKey: Uint8Array): Promise<string> {\n const { encryptedSeedlessEncryptionKey: encryptedKey } = this.state;\n assertIsEncryptedSeedlessEncryptionKeySet(encryptedKey);\n const encryptedKeyBytes = base64ToBytes(encryptedKey);\n const aes = managedNonce(gcm)(encKey);\n const seedlessEncryptionKey = aes.decrypt(encryptedKeyBytes);\n return bytesToUtf8(seedlessEncryptionKey);\n }\n\n /**\n * Recover the authentication public key from the state.\n * convert to pubkey format before recovering.\n *\n * @returns The authentication public key.\n */\n #recoverAuthPubKey(): SEC1EncodedPublicKey {\n const { authPubKey } = this.state;\n if (!authPubKey) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.SRPNotBackedUpError,\n );\n }\n\n return base64ToBytes(authPubKey);\n }\n\n /**\n * Recover the encryption key from password.\n *\n * @param password - The password used to derive/recover the encryption key.\n * @returns A promise that resolves to the encryption key and authentication key pair.\n * @throws RecoveryError - If failed to recover the encryption key.\n */\n async #recoverEncKey(\n password: string,\n ): Promise<Omit<RecoverEncryptionKeyResult, 'rateLimitResetResult'>> {\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens,\n password,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n // throw token expired error for token refresh handler\n if (isAuthTokenError(error)) {\n throw error;\n }\n\n throw RecoveryError.getInstance(error);\n }\n }\n\n async #fetchAllSecretDataFromMetadataStore(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): Promise<SecretMetadata[]> {\n let secretDataItems: FetchedSecretDataItem[] = [];\n try {\n // fetch and decrypt the secret data from the metadata store\n secretDataItems = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n } catch (error) {\n log('Error fetching secret data', error);\n if (isAuthTokenError(error)) {\n throw error;\n }\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchSecretMetadata,\n {\n cause: error,\n },\n );\n }\n\n // user must have at least one secret data\n if (secretDataItems?.length > 0) {\n return parseAndValidateSecretMetadataBackup(secretDataItems);\n }\n\n throw new Error(SeedlessOnboardingControllerErrorMessage.NoSecretDataFound);\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param params - The function parameters.\n * @param params.oldPassword - The old password to verify.\n * @param params.newPassword - The new password to update.\n * @param params.latestKeyIndex - The key index of the latest key.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey({\n oldPassword,\n newPassword,\n latestKeyIndex,\n }: {\n newPassword: string;\n oldPassword: string;\n latestKeyIndex?: number;\n }): Promise<ChangeEncryptionKeyResult> {\n this.#assertIsAuthenticatedUser(this.state);\n const { authConnectionId, groupedAuthConnectionId, userId } = this.state;\n\n let encKey: Uint8Array;\n let pwEncKey: Uint8Array;\n let authKeyPair: KeyPair;\n let globalKeyIndex = latestKeyIndex;\n if (globalKeyIndex) {\n ({\n toprfEncryptionKey: encKey,\n toprfPwEncryptionKey: pwEncKey,\n toprfAuthKeyPair: authKeyPair,\n } = await this.#unlockVaultAndGetVaultData({ password: oldPassword }));\n } else {\n ({\n encKey,\n pwEncKey,\n authKeyPair,\n keyShareIndex: globalKeyIndex,\n } = await this.#recoverEncKey(oldPassword));\n }\n const result = await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n oldEncKey: encKey,\n oldPwEncKey: pwEncKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex: globalKeyIndex,\n newPassword,\n transformDataItems: (items) =>\n items\n .sort((a, b) =>\n SecretMetadata.compare(\n SecretMetadata.fromRawMetadata(a.data, { dataType: a.dataType }),\n SecretMetadata.fromRawMetadata(b.data, { dataType: b.dataType }),\n 'asc',\n ),\n )\n .map(({ data, dataType, version }) => ({\n data,\n dataType,\n version: dataType === undefined ? 'v1' : version,\n })),\n });\n return result;\n }\n\n /**\n * Encrypt and store the secret data backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the secret data backup.\n * @param params.data - The secret data to store.\n * @param params.dataType - The data type classification for the secret data.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n * @param params.options - Optional options object.\n * @param params.options.keyringId - The keyring id of the backup keyring (required for SRP types).\n * @param params.skipStatePersist - Whether to persist the backup state after\n * the remote metadata is stored. When true, the backup metadata is not persisted to the controller state.\n *\n * @returns A promise that resolves to the backup metadata.\n */\n async #encryptAndStoreSecretData(params: {\n data: Uint8Array;\n dataType: EncAccountDataType;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n options?: {\n keyringId?: string;\n };\n skipStatePersist?: boolean;\n }): Promise<SecretMetadata> {\n const {\n options,\n data,\n encKey,\n authKeyPair,\n dataType,\n skipStatePersist = false,\n } = params;\n\n const secretMetadata = new SecretMetadata(data, { dataType });\n const { type } = secretMetadata;\n\n // before encrypting and create backup, we will check the state if the secret data is already backed up\n const backupState = this.getSecretDataBackupState(data, type);\n if (backupState) {\n return secretMetadata;\n }\n\n const secretData = secretMetadata.toBytes();\n\n const keyringId = options?.keyringId as string;\n if (type === SecretType.Mnemonic && !keyringId) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MissingKeyringId,\n );\n }\n\n try {\n const persistMetadataFn = async (): Promise<\n Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array }\n > => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n dataType,\n });\n return {\n keyringId,\n data,\n type,\n };\n };\n\n // Skip local persistence if `skipStatePersist` is true.\n if (skipStatePersist) {\n await persistMetadataFn();\n } else {\n await this.#withPersistedSecretMetadataBackupsState(persistMetadataFn);\n }\n\n return secretMetadata;\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n log('Error encrypting and storing secret data backup', error);\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.FailedToEncryptAndStoreSecretData,\n );\n }\n }\n\n /**\n * Unlocks the encrypted vault using the provided password and returns the decrypted vault data.\n * This method ensures thread-safety by using a mutex lock when accessing the vault.\n *\n * @param params - The parameters for unlocking the vault.\n * @param params.password - The optional password to unlock the vault.\n * @param params.encryptionKey - The optional encryption key to unlock the vault.\n * @returns A promise that resolves to an object containing:\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\n * - revokeToken: The decrypted revoke token\n * - accessToken: The decrypted access token\n * @throws {Error} If:\n * - The password is invalid or empty\n * - The vault is not initialized\n * - The password is incorrect (from encryptor.decrypt)\n * - The decrypted vault data is malformed\n */\n async #unlockVaultAndGetVaultData(params?: {\n password?: string;\n encryptionKey?: string;\n }): Promise<DeserializedVaultData> {\n return this.#withVaultLock(async () => {\n if (this.#cachedDecryptedVaultData) {\n return this.#cachedDecryptedVaultData;\n }\n\n const { vaultData, vaultEncryptionKey, vaultEncryptionSalt } =\n await this.#decryptAndParseVaultData(params);\n\n this.update((state) => {\n state.vaultEncryptionKey = vaultEncryptionKey;\n state.vaultEncryptionSalt = vaultEncryptionSalt;\n state.revokeToken = vaultData.revokeToken;\n state.accessToken = vaultData.accessToken;\n });\n\n const deserializedVaultData = deserializeVaultData(vaultData);\n this.#cachedDecryptedVaultData = deserializedVaultData;\n return deserializedVaultData;\n });\n }\n\n /**\n * Decrypts the vault data and parses it into a usable format.\n *\n * @param params - The parameters for decrypting the vault.\n * @param params.password - The optional password to decrypt the vault.\n * @param params.encryptionKey - The optional encryption key to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n */\n async #decryptAndParseVaultData(params?: {\n password?: string;\n encryptionKey?: string;\n }): Promise<{\n vaultData: VaultData;\n vaultEncryptionKey: string;\n vaultEncryptionSalt?: string;\n }> {\n let { vaultEncryptionKey, vaultEncryptionSalt } = this.state;\n const { vault: encryptedVault } = this.state;\n\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultError);\n }\n\n if (params?.encryptionKey) {\n vaultEncryptionKey = params.encryptionKey;\n }\n\n let decryptedVaultData: unknown;\n\n // if the encryption key is available, we will use it to decrypt the vault\n if (vaultEncryptionKey) {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (\n vaultEncryptionSalt &&\n vaultEncryptionSalt !== parsedEncryptedVault.salt\n ) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.ExpiredCredentials,\n );\n }\n\n const key = await this.#vaultEncryptor.importKey(vaultEncryptionKey);\n decryptedVaultData = await this.#vaultEncryptor.decryptWithKey(\n key,\n parsedEncryptedVault,\n );\n } else {\n // if the encryption key is not available, we will use the password to decrypt the vault\n assertIsValidPassword(params?.password);\n // Note that vault decryption using the password is a very costly operation as it involves deriving the encryption key\n // from the password using an intentionally slow key derivation function.\n // We should make sure that we only call it very intentionally.\n const result = await this.#vaultEncryptor.decryptWithDetail(\n params.password,\n encryptedVault,\n );\n decryptedVaultData = result.vault;\n vaultEncryptionKey = result.exportedKeyString;\n vaultEncryptionSalt = result.salt;\n }\n\n const vaultData = parseVaultData(decryptedVaultData);\n\n return {\n vaultData,\n vaultEncryptionKey,\n vaultEncryptionSalt,\n };\n }\n\n /**\n * Executes a callback function that creates or restores secret data and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore secret data\n * 2. Generates keccak256 hashes of the secret data\n * 3. Merges new hashes with existing ones in the state, ensuring uniqueness\n * 4. Updates the controller state with the combined hashes\n *\n * This is a wrapper method that should be used around any operation that creates\n * or restores secret data to ensure their hashes are properly tracked.\n *\n * @param createSecretMetadataBackupCallback - function that returns either a single secret data\n * or an array of secret data as Uint8Array(s)\n * @returns The original secret data(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSecretMetadataBackupsState(\n createSecretMetadataBackupCallback: () => Promise<SecretBackupData>,\n ): Promise<SecretBackupData> {\n try {\n const newBackup = await createSecretMetadataBackupCallback();\n\n this.#filterDupesAndUpdateSocialBackupsMetadata(newBackup);\n\n return newBackup;\n } catch (error) {\n log('Error persisting secret data backups', error);\n throw error;\n }\n }\n\n /**\n * Updates the social backups metadata state by adding new unique secret data backups.\n * This method ensures no duplicate backups are stored by checking the hash of each secret data.\n *\n * @param secretData - The backup data to add to the state\n * @param secretData.data - The secret data to backup as a Uint8Array\n * @param secretData.keyringId - The optional keyring id of the backup keyring (SRP).\n * @param secretData.type - The type of the secret data.\n */\n #filterDupesAndUpdateSocialBackupsMetadata(\n secretData: SecretBackupData | SecretBackupData[],\n ): void {\n const filteredNewBackupsMetadata = getNewSocialBackupsMetadata(\n this.state.socialBackupsMetadata,\n secretData,\n );\n\n if (filteredNewBackupsMetadata.length > 0) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n ...filteredNewBackupsMetadata,\n ];\n });\n }\n }\n\n /**\n * Create a new vault with the given authentication data.\n *\n * Serialize the authentication and key data which will be stored in the vault.\n *\n * @param params - The parameters for creating a new vault.\n * @param params.password - The password to encrypt the vault.\n * @param params.rawToprfEncryptionKey - The encryption key to encrypt the vault.\n * @param params.rawToprfPwEncryptionKey - The encryption key to encrypt the password.\n * @param params.rawToprfAuthKeyPair - The authentication key pair for Toprf operations.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfPwEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array;\n rawToprfPwEncryptionKey: Uint8Array;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { accessToken, revokeToken } =\n await this.#getAccessTokenAndRevokeToken(password);\n\n const vaultData: DeserializedVaultData = {\n toprfAuthKeyPair: rawToprfAuthKeyPair,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfPwEncryptionKey: rawToprfPwEncryptionKey,\n revokeToken,\n accessToken,\n };\n\n await this.#updateVault({\n password,\n vaultData,\n pwEncKey: rawToprfPwEncryptionKey,\n });\n\n // update the authPubKey in the state\n this.#persistAuthPubKey({\n authPubKey: rawToprfAuthKeyPair.pk,\n });\n\n this.#setUnlocked();\n }\n\n /**\n * Encrypt and update the vault with the given authentication data.\n *\n * @param params - The parameters for updating the vault.\n * @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.\n * @param params.vaultData - The raw vault data to update the vault with.\n * @param params.pwEncKey - The global password encryption key.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n vaultData,\n pwEncKey,\n }: {\n password?: string;\n vaultData: DeserializedVaultData;\n pwEncKey: Uint8Array;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n const serializedVaultData = serializeVaultData(vaultData);\n\n const { vaultEncryptionKey, vaultEncryptionSalt, vault } = this.state;\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {\n vault,\n vaultEncryptionKey,\n vaultEncryptionSalt,\n encryptedSeedlessEncryptionKey:\n this.state.encryptedSeedlessEncryptionKey,\n };\n\n // if the password is provided (not undefined), encrypt the vault with the password\n // We gonna prioritize the password encryption here, in case of the operation is `Change Password`.\n // We don't wanna re-use the old encryption key from the state.\n if (password !== undefined) {\n assertIsValidPassword(password);\n\n // Note that vault encryption using the password is a very costly operation as it involves deriving the encryption key\n // from the password using an intentionally slow key derivation function.\n // We should make sure that we only call it very intentionally.\n const { vault: updatedEncVault, exportedKeyString } =\n await this.#vaultEncryptor.encryptWithDetail(\n password,\n serializedVaultData,\n );\n\n updatedState.vault = updatedEncVault;\n updatedState.vaultEncryptionKey = exportedKeyString;\n updatedState.vaultEncryptionSalt = JSON.parse(updatedEncVault).salt;\n\n // encrypt the seedless encryption key with the password encryption key from TOPRF network\n updatedState.encryptedSeedlessEncryptionKey =\n this.#encryptSeedlessEncryptionKey(exportedKeyString, pwEncKey);\n } else if (vaultEncryptionKey && vaultEncryptionSalt) {\n const encryptionKey =\n await this.#vaultEncryptor.importKey(vaultEncryptionKey);\n const updatedEncVault = await this.#vaultEncryptor.encryptWithKey(\n encryptionKey,\n serializedVaultData,\n );\n\n // NOTE: Referenced from keyring-controller!\n // We need to include the salt used to derive the encryption key, to be able to derive it from password again.\n updatedEncVault.salt = vaultEncryptionSalt;\n\n updatedState.vault = JSON.stringify(updatedEncVault);\n updatedState.vaultEncryptionKey = vaultEncryptionKey;\n updatedState.vaultEncryptionSalt = vaultEncryptionSalt;\n } else {\n // neither password nor encryption key is provided\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MissingCredentials,\n );\n }\n\n // update the state with the updated vault data\n this.update((state) => {\n state.vault = updatedState.vault;\n state.vaultEncryptionKey = updatedState.vaultEncryptionKey;\n state.vaultEncryptionSalt = updatedState.vaultEncryptionSalt;\n state.encryptedSeedlessEncryptionKey =\n updatedState.encryptedSeedlessEncryptionKey;\n });\n\n // cache the vault data to avoid decrypting the vault data multiple times\n this.#cachedDecryptedVaultData = vaultData;\n });\n }\n\n /**\n * Encrypt the seedless encryption key with the password encryption key from TOPRF network.\n *\n * @param vaultEncryptionKey - The key which is used to encrypt the vault.\n * @param pwEncKey - The password encryption key from TOPRF network.\n * @returns The encrypted seedless encryption key.\n */\n #encryptSeedlessEncryptionKey(\n vaultEncryptionKey: string,\n pwEncKey: Uint8Array,\n ): string {\n const aes = managedNonce(gcm)(pwEncKey);\n const encryptedKey = aes.encrypt(utf8ToBytes(vaultEncryptionKey));\n return bytesToBase64(encryptedKey);\n }\n\n /**\n * Get the access token and revoke token from the state or the vault.\n *\n * @param password - The password to decrypt the vault.\n * @returns The access token and revoke token.\n */\n async #getAccessTokenAndRevokeToken(\n password: string,\n ): Promise<{ accessToken: string; revokeToken: string }> {\n let { accessToken, revokeToken } = this.state;\n // `accessToken` and `revokeToken` are both available in the state, `ONLY` when the wallet (vault) is unlocked\n // or during the period between the social authentication and the vault creation during the onboarding flow.\n if (accessToken && revokeToken) {\n return { accessToken, revokeToken };\n }\n\n // if `password` is provided to decrypt the vault, decrypt the vault and get the access token and revoke token from the vault\n if (this.state.vault) {\n // if the access token or revoke token is not available in the state, decrypt the vault and get the access token and revoke token from the vault\n const { vaultData } = await this.#decryptAndParseVaultData({ password });\n accessToken = accessToken ?? vaultData.accessToken;\n revokeToken = revokeToken ?? vaultData.revokeToken;\n }\n\n // we should always throw an error if the access token or revoke token is not available\n // to prevent the caller from using the controller in an invalid state\n\n if (!accessToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidAccessToken,\n );\n }\n\n if (!revokeToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidRevokeToken,\n );\n }\n\n return { accessToken, revokeToken };\n }\n\n /**\n * Lock the controller mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * This wrapper ensures that each mutable operation that interacts with the\n * controller and that changes its state is executed in a mutually exclusive way,\n * preventing unsafe concurrent access that could lead to unpredictable behavior.\n *\n * @param callback - The function to execute while the controller mutex is locked.\n * @returns The result of the function.\n */\n async #withControllerLock<Result>(\n callback: MutuallyExclusiveCallback<Result>,\n ): Promise<Result> {\n return await withLock(this.#controllerOperationMutex, callback);\n }\n\n /**\n * Lock the vault mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * This ensures that each operation that interacts with the vault\n * is executed in a mutually exclusive way.\n *\n * @param callback - The function to execute while the vault mutex is locked.\n * @returns The result of the function.\n */\n async #withVaultLock<Result>(\n callback: MutuallyExclusiveCallback<Result>,\n ): Promise<Result> {\n return await withLock(this.#vaultOperationMutex, callback);\n }\n\n #assertIsUnlocked(): void {\n if (!this.#isUnlocked) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.ControllerLocked,\n );\n }\n }\n\n /**\n * Assert that the provided value contains valid authenticated user information.\n *\n * This method checks that the value is an object containing:\n * - nodeAuthTokens: A non-empty array of authentication tokens\n * - authConnectionId: A string identifier for the OAuth connection\n * - groupedAuthConnectionId: A string identifier for grouped OAuth connections\n * - userId: A string identifier for the authenticated user\n *\n * @param value - The value to validate.\n * @throws {Error} If the value does not contain valid authenticated user information.\n */\n #assertIsAuthenticatedUser(\n value: unknown,\n ): asserts value is AuthenticatedUserDetails {\n try {\n assertIsSeedlessOnboardingUserAuthenticated(value);\n } catch (error) {\n this.update((state) => {\n state.isSeedlessOnboardingUserAuthenticated = false;\n });\n throw error;\n }\n }\n\n /**\n * Assert that the password is in sync with the global password.\n *\n * @param options - The options for asserting the password is in sync.\n * @param options.skipCache - Whether to skip the cache check.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns The global auth public key and the latest key index.\n * @throws If the password is outdated.\n */\n async #assertPasswordInSync(options?: {\n skipCache?: boolean;\n skipLock?: boolean;\n }): Promise<{\n authPubKey: SEC1EncodedPublicKey;\n latestKeyIndex: number;\n }> {\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n const { authPubKey, keyIndex: latestKeyIndex } = await this.toprfClient\n .fetchAuthPubKey({\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n })\n .catch((error) => {\n log('Error fetching auth pub key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchAuthPubKey,\n {\n cause: error,\n },\n );\n });\n const isPasswordOutdated = await this.checkIsPasswordOutdated({\n ...options,\n globalAuthPubKey: authPubKey,\n });\n if (isPasswordOutdated) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.OutdatedPassword,\n );\n }\n return { authPubKey, latestKeyIndex };\n }\n\n #resetPasswordOutdatedCache(): void {\n this.update((state) => {\n delete state.passwordOutdatedCache;\n });\n }\n\n /**\n * Refresh expired nodeAuthTokens, accessToken, and metadataAccessToken using\n * the stored refresh token.\n *\n * Concurrent callers share a single in-flight HTTP request — if a refresh is\n * already in-progress the returned promise resolves when that request settles\n * rather than firing a duplicate request with the same token.\n *\n * @returns A promise that resolves when the tokens have been refreshed.\n */\n async refreshAuthTokens(): Promise<void> {\n // Coalesce concurrent calls to avoid issuing parallel HTTP requests\n // with the same refresh token.\n if (this.#pendingRefreshPromise) {\n return this.#pendingRefreshPromise;\n }\n\n const promise = this.#doRefreshAuthTokens().finally(() => {\n if (this.#pendingRefreshPromise === promise) {\n this.#pendingRefreshPromise = undefined;\n }\n });\n\n this.#pendingRefreshPromise = promise;\n\n return promise;\n }\n\n /**\n * Internal implementation of token refresh. Called exclusively by\n * `refreshAuthTokens` which gates concurrent access via\n * `#pendingRefreshPromise`.\n */\n async #doRefreshAuthTokens(): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n const { refreshToken } = this.state;\n\n const res = await this.#refreshJWTToken({\n connection: this.state.authConnection,\n refreshToken,\n }).catch((error) => {\n // Distinguish a server-side token rejection (401) from transient\n // failures so callers can apply the appropriate recovery strategy.\n const httpStatusCode = (error as Error & { statusCode?: number })\n .statusCode;\n log('Error refreshing JWT tokens', error, { httpStatusCode });\n const isTokenRevoked =\n error instanceof Error &&\n error.name === 'RefreshTokenHttpError' &&\n httpStatusCode === 401;\n throw new SeedlessOnboardingError(\n isTokenRevoked\n ? SeedlessOnboardingControllerErrorMessage.InvalidRefreshToken\n : SeedlessOnboardingControllerErrorMessage.FailedToRefreshJWTTokens,\n {\n cause: error,\n },\n );\n });\n\n try {\n const { idTokens, accessToken, metadataAccessToken } = res;\n // Re-authenticate with the refreshed id tokens to update node auth\n // tokens, accessToken, and metadataAccessToken in state.\n await this.#reAuthenticate({\n idTokens,\n accessToken,\n metadataAccessToken,\n });\n\n // update the vault with new access token if wallet is unlocked\n if (this.#isUnlocked && this.#cachedDecryptedVaultData) {\n const updatedVaultData = {\n ...this.#cachedDecryptedVaultData,\n accessToken,\n };\n const pwEncKey = this.#cachedDecryptedVaultData.toprfPwEncryptionKey;\n\n await this.#updateVault({\n vaultData: updatedVaultData,\n pwEncKey,\n });\n\n // Proactively rotate the refresh token now that we have vault access.\n await this.rotateRefreshToken().catch((error) => {\n // Rotation failure is intentionally non-fatal: the JWT refresh\n // itself succeeded and the caller should not be blocked.\n // However the user is now operating with a stale refresh token\n // that may be revoked server-side, so log prominently.\n log(\n 'Failed to rotate refresh token after successful JWT refresh. ' +\n 'The user may be logged out when the old token is revoked.',\n error,\n );\n });\n }\n } catch (error) {\n log('Error refreshing node auth tokens', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Re-authenticate the user using freshly issued tokens from a JWT refresh.\n *\n * Unlike the public `authenticate` method, this variant is called exclusively\n * from token-refresh paths where the user's identity has already been\n * established. It only accepts the tokens returned by the JWT-refresh\n * service (`idTokens`, `accessToken`, `metadataAccessToken`) and reads all\n * other auth-connection details from the existing controller state.\n *\n * `refreshToken` and `revokeToken` are intentionally absent — token-refresh\n * paths must not touch `state.refreshToken` directly; that field is managed\n * exclusively by `rotateRefreshToken`.\n *\n * @param params - Tokens issued by the JWT-refresh service.\n * @param params.idTokens - New node id tokens.\n * @param params.accessToken - New access token.\n * @param params.metadataAccessToken - New metadata access token.\n * @returns A promise that resolves to the authentication result.\n */\n async #reAuthenticate(params: {\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n }): Promise<AuthenticateResult> {\n const { idTokens, accessToken, metadataAccessToken } = params;\n const {\n authConnection,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n socialLoginEmail,\n } = this.state;\n\n try {\n const authenticationResult = await this.toprfClient.authenticate({\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n authConnectionId: authConnectionId!,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n userId: userId!,\n idTokens,\n groupedAuthConnectionId,\n });\n\n this.update((state) => {\n state.nodeAuthTokens = authenticationResult.nodeAuthTokens;\n state.authConnection = authConnection;\n state.authConnectionId = authConnectionId;\n state.groupedAuthConnectionId = groupedAuthConnectionId;\n state.userId = userId;\n state.socialLoginEmail = socialLoginEmail;\n state.metadataAccessToken = metadataAccessToken;\n state.accessToken = accessToken;\n assertIsSeedlessOnboardingUserAuthenticated(state);\n state.isSeedlessOnboardingUserAuthenticated = true;\n });\n\n return authenticationResult;\n } catch (error) {\n log('Error re-authenticating user', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Rotate the refresh token — fetch a new refresh/revoke token pair from the\n * auth service and persist the new revoke token in the vault.\n *\n * This method should be called after a successful JWT refresh.\n *\n * @returns A Promise that resolves to void.\n */\n async rotateRefreshToken(): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const vaultData = this.#cachedDecryptedVaultData;\n // Safety net: the caller (#doRefreshAuthTokens) already guards with\n // `this.#isUnlocked && this.#cachedDecryptedVaultData`, so this branch\n // is unreachable in normal flow. This check is added to satisfy the linter and\n // to make sure any future caller of this method does not bypass the check.\n /* istanbul ignore if */\n if (!vaultData) {\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.VaultLocked,\n );\n }\n const { refreshToken } = this.state;\n const { toprfPwEncryptionKey: pwEncKey, revokeToken } = vaultData;\n const { newRevokeToken, newRefreshToken } = await this.#renewRefreshToken({\n connection: this.state.authConnection,\n revokeToken,\n });\n\n if (newRevokeToken && newRefreshToken) {\n // Persist the new revoke token to the vault first. Only update state after\n // the vault write succeeds, so state and vault stay in sync if the write fails.\n await this.#updateVault({\n vaultData: {\n ...vaultData,\n revokeToken: newRevokeToken,\n },\n pwEncKey,\n });\n\n this.update((state) => {\n state.revokeToken = newRevokeToken;\n state.refreshToken = newRefreshToken;\n });\n\n // add the old refresh token to the list to be revoked later when possible\n this.#addRefreshTokenToRevokeList({\n refreshToken,\n revokeToken,\n });\n }\n }\n\n /**\n * Revoke all pending refresh tokens.\n *\n * This method is to be called after user is authenticated.\n *\n * @returns A Promise that resolves to void.\n */\n async revokePendingRefreshTokens(): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsAuthenticatedUser(this.state);\n const { pendingToBeRevokedTokens } = this.state;\n if (!pendingToBeRevokedTokens || pendingToBeRevokedTokens.length === 0) {\n return;\n }\n\n // revoke all pending refresh tokens in parallel\n const promises = pendingToBeRevokedTokens.map(({ revokeToken }) => {\n const revokePromise = async (): Promise<string | null> => {\n try {\n await this.#revokeRefreshToken({\n connection: this.state.authConnection as AuthConnection,\n revokeToken,\n });\n return revokeToken;\n } catch (error) {\n log('Error revoking refresh token', error);\n return null;\n }\n };\n return revokePromise();\n });\n const result = await Promise.all(promises); // no need to do Promise.allSettled because the promise already handle try catch\n // filter out the null values\n const revokedTokens = result.filter((token) => token !== null);\n if (revokedTokens.length > 0) {\n // update the state to remove the revoked tokens once all concurrent token revoke finish\n this.update((state) => {\n state.pendingToBeRevokedTokens =\n state.pendingToBeRevokedTokens?.filter(\n (token) => !revokedTokens.includes(token.revokeToken),\n );\n });\n }\n });\n }\n\n /**\n * Get the access token from the state.\n *\n * If the tokens are expired, the method will refresh them and return the new access token.\n *\n * @returns The access token.\n */\n async getAccessToken(): Promise<string | undefined> {\n return this.#withControllerLock(async () => {\n this.#assertIsAuthenticatedUser(this.state);\n\n return this.#executeWithTokenRefresh(async () => {\n return this.state.accessToken;\n }, 'getAccessToken');\n });\n }\n\n /**\n * Add a pending refresh, revoke token to the state to be revoked later.\n *\n * @param params - The parameters for adding a pending refresh, revoke token.\n * @param params.refreshToken - The refresh token to add.\n * @param params.revokeToken - The revoke token to add.\n */\n #addRefreshTokenToRevokeList({\n refreshToken,\n revokeToken,\n }: {\n refreshToken: string;\n revokeToken: string;\n }): void {\n this.update((state) => {\n state.pendingToBeRevokedTokens = [\n ...(state.pendingToBeRevokedTokens ?? []),\n { refreshToken, revokeToken },\n ];\n });\n }\n\n /**\n * Executes an operation with automatic token refresh on expiration.\n *\n * This wrapper method automatically handles token expiration by refreshing tokens\n * and retrying the operation. It can be used by any method that might encounter\n * token expiration errors.\n *\n * @param operation - The operation to execute that might require valid tokens.\n * @param operationName - A descriptive name for the operation (used in error messages).\n * @returns A promise that resolves to the result of the operation.\n * @throws The original error if it's not token-related, or refresh error if token refresh fails.\n */\n async #executeWithTokenRefresh<Result>(\n operation: () => Promise<Result>,\n operationName: string,\n ): Promise<Result> {\n try {\n if (this.#checkTokensExpired()) {\n log(\n `JWT token expired during ${operationName}, attempting to refresh tokens`,\n 'node auth token exp check',\n );\n await this.refreshAuthTokens();\n }\n\n return await operation();\n } catch (error) {\n // Check if this is a token expiration error\n if (isAuthTokenError(error)) {\n log(\n `Token expired during ${operationName}, attempting to refresh tokens`,\n error,\n );\n try {\n // Refresh the tokens\n await this.refreshAuthTokens();\n // Retry the operation with fresh tokens\n return await operation();\n } catch (refreshError) {\n log(`Error refreshing tokens during ${operationName}`, refreshError);\n throw refreshError;\n }\n } else {\n // Re-throw non-token-related errors\n throw error;\n }\n }\n }\n\n /**\n * Check if the tokens are expired.\n *\n * @returns True if the tokens are expired, false otherwise.\n */\n #checkTokensExpired(): boolean {\n // proactively check for expired tokens and refresh them if needed\n const isNodeAuthTokenExpired = this.checkNodeAuthTokenExpired();\n const isMetadataAccessTokenExpired = this.checkMetadataAccessTokenExpired();\n // access token is only accessible when the vault is unlocked\n // so skip the check if the vault is locked\n let isAccessTokenExpired = false;\n if (this.#isUnlocked) {\n isAccessTokenExpired = this.checkAccessTokenExpired();\n }\n\n return (\n isNodeAuthTokenExpired ||\n isMetadataAccessTokenExpired ||\n isAccessTokenExpired\n );\n }\n\n /**\n * Check if the current node auth token is expired.\n *\n * @returns True if the current node auth token is expired, false otherwise.\n */\n public checkNodeAuthTokenExpired(): boolean {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { nodeAuthTokens } = this.state;\n // all auth tokens should be expired at the same time so we can check the first one\n const firstAuthToken = nodeAuthTokens[0]?.authToken;\n // node auth token is base64 encoded json object\n const decodedToken = decodeNodeAuthToken(firstAuthToken);\n // Node auth tokens do not carry a reliable iat field — use exact expiry.\n return isTokenNearExpiry(decodedToken.exp);\n }\n\n /**\n * Check if the current metadata access token should be refreshed.\n * Returns true when the token is expired or when less than 10% of its\n * lifetime remains (proactive refresh).\n *\n * @returns True if the metadata access token should be refreshed, false otherwise.\n */\n public checkMetadataAccessTokenExpired(): boolean {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n const { metadataAccessToken } = this.state;\n // assertIsAuthenticatedUser will throw if metadataAccessToken is missing\n const decodedToken = decodeJWTToken(metadataAccessToken as string);\n return isTokenNearExpiry(decodedToken.exp, decodedToken.iat);\n } catch {\n return true; // Consider unauthenticated user as having expired tokens\n }\n }\n\n /**\n * Check if the current access token should be refreshed.\n * Returns true when the token is expired or when less than 10% of its\n * lifetime remains (proactive refresh).\n * When the vault is locked, the access token is not accessible, so we return false.\n *\n * @returns True if the access token should be refreshed, false otherwise.\n */\n public checkAccessTokenExpired(): boolean {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n const { accessToken } = this.state;\n if (!accessToken) {\n return true; // Consider missing token as expired\n }\n const decodedToken = decodeJWTToken(accessToken);\n return isTokenNearExpiry(decodedToken.exp, decodedToken.iat);\n } catch {\n return true; // Consider unauthenticated user as having expired tokens\n }\n }\n\n async #identifyIncompleteMetadataBackup(password: string): Promise<void> {\n const deserializedVaultData =\n this.#cachedDecryptedVaultData as DeserializedVaultData;\n\n await trackIncompleteMetadataBackupEvents({\n fetchAllSecretDataFn: () =>\n this.toprfClient.fetchAllSecretDataItems({\n decKey: deserializedVaultData.toprfEncryptionKey,\n authKeyPair: deserializedVaultData.toprfAuthKeyPair,\n }),\n getPrimaryKeyringSeedPhraseFn: () =>\n this.messenger.call('KeyringController:exportSeedPhrase', {\n password,\n }),\n trackEvent: (event) =>\n this.messenger.call('AnalyticsController:trackEvent', event),\n logFn: log,\n });\n }\n}\n\n/**\n * Lock the given mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * @param mutex - The mutex to lock.\n * @param callback - The function to execute while the mutex is locked.\n * @returns The result of the function.\n */\nasync function withLock<Result>(\n mutex: Mutex,\n callback: MutuallyExclusiveCallback<Result>,\n): Promise<Result> {\n const releaseLock = await mutex.acquire();\n\n try {\n return await callback({ releaseLock });\n } finally {\n releaseLock();\n }\n}\n"]}
1
+ {"version":3,"file":"SeedlessOnboardingController.js","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport { BaseController } from '@metamask/base-controller';\nimport type * as encryptionUtils from '@metamask/browser-passworder';\nimport { decrypt, encrypt, IV_LENGTH } from '@metamask/cryptography/aes-gcm';\nimport type {\n DefaultEncryptionResult,\n EncryptionResultConstraint,\n Encryptor,\n} from '@metamask/keyring-controller';\nimport type {\n AuthenticateResult,\n ChangeEncryptionKeyResult,\n KeyPair,\n RecoverEncryptionKeyResult,\n SEC1EncodedPublicKey,\n FetchedSecretDataItem,\n} from '@metamask/toprf-secure-backup';\nimport {\n ToprfSecureBackup,\n EncAccountDataType,\n} from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bytesToBase64,\n bytesToString,\n stringToBytes,\n concatBytes,\n} from '@metamask/utils';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { Mutex } from 'async-mutex';\n\nimport type { AuthConnection } from './constants.js';\nimport {\n controllerName,\n PASSWORD_OUTDATED_CACHE_TTL_MS,\n SecretType,\n SeedlessOnboardingControllerErrorMessage,\n SeedlessOnboardingMigrationVersion,\n Web3AuthNetwork,\n} from './constants.js';\nimport {\n PasswordSyncError,\n RecoveryError,\n SeedlessOnboardingError,\n} from './errors.js';\nimport { projectLogger, createModuleLogger } from './logger.js';\nimport { SecretMetadata } from './SecretMetadata.js';\nimport type {\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n} from './SeedlessOnboardingController-types.js';\nimport {\n getInitialSeedlessOnboardingControllerStateWithDefaults,\n seedlessOnboardingMetadata,\n} from './state.js';\nimport type {\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerState,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n RefreshJWTToken,\n RevokeRefreshToken,\n RenewRefreshToken,\n VaultData,\n DeserializedVaultData,\n} from './types.js';\nimport {\n assertIsEncryptedKeyringEncryptionKeySet,\n assertIsEncryptedSeedlessEncryptionKeySet,\n assertIsPasswordOutdatedCacheValid,\n assertIsSeedlessOnboardingUserAuthenticated,\n assertIsValidPassword,\n compareAndGetLatestToken,\n decodeJWTToken,\n decodeNodeAuthToken,\n deserializeVaultData,\n getDataTypeMigrationUpdates,\n getNewSocialBackupsMetadata,\n trackIncompleteMetadataBackupEvents,\n isAuthTokenError,\n isMaxKeyChainLengthError,\n isTokenNearExpiry,\n parseVaultData,\n parseAndValidateSecretMetadataBackup,\n serializeVaultData,\n} from './utils/index.js';\nimport type { SecretBackupData } from './utils/index.js';\n\nexport type {\n SeedlessOnboardingControllerActions,\n SeedlessOnboardingControllerEvents,\n SeedlessOnboardingControllerGetStateAction,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerStateChangeEvent,\n} from './SeedlessOnboardingController-types.js';\nexport { getInitialSeedlessOnboardingControllerStateWithDefaults } from './state.js';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'fetchMetadataAccessCreds',\n 'preloadToprfNodeDetails',\n 'authenticate',\n 'createToprfKeyAndBackupSeedPhrase',\n 'addNewSecretData',\n 'fetchAllSecretData',\n 'changePassword',\n 'updateBackupMetadataState',\n 'verifyVaultPassword',\n 'getSecretDataBackupState',\n 'submitPassword',\n 'identifyIncompleteMetadataBackup',\n 'setLocked',\n 'syncLatestGlobalPassword',\n 'submitGlobalPassword',\n 'checkIsPasswordOutdated',\n 'getIsUserAuthenticated',\n 'clearState',\n 'storeKeyringEncryptionKey',\n 'loadKeyringEncryptionKey',\n 'refreshAuthTokens',\n 'revokePendingRefreshTokens',\n 'rotateRefreshToken',\n 'getAccessToken',\n 'checkNodeAuthTokenExpired',\n 'checkMetadataAccessTokenExpired',\n 'checkAccessTokenExpired',\n 'runMigrations',\n] as const;\n\nexport class SeedlessOnboardingController<\n EncryptionKey = encryptionUtils.EncryptionKey,\n SupportedKeyDerivationOptions = encryptionUtils.KeyDerivationOptions,\n EncryptionResult extends\n EncryptionResultConstraint<SupportedKeyDerivationOptions> =\n DefaultEncryptionResult<SupportedKeyDerivationOptions>,\n> extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: Encryptor<\n EncryptionKey,\n SupportedKeyDerivationOptions,\n EncryptionResult\n >;\n\n readonly #controllerOperationMutex = new Mutex();\n\n readonly #vaultOperationMutex = new Mutex();\n\n /**\n * In-flight promise for `refreshAuthTokens`. Any concurrent caller that\n * arrives while a refresh is already in-progress will share this promise\n * rather than issuing a second HTTP request with the same refresh token.\n */\n #pendingRefreshPromise: Promise<void> | undefined;\n\n readonly toprfClient: ToprfSecureBackup;\n\n readonly #refreshJWTToken: RefreshJWTToken;\n\n readonly #revokeRefreshToken: RevokeRefreshToken;\n\n readonly #renewRefreshToken: RenewRefreshToken;\n\n /**\n * The TTL of the password outdated cache in milliseconds.\n */\n readonly #passwordOutdatedCacheTTL: number;\n\n /**\n * Controller lock state.\n *\n * The controller lock is synchronized with the keyring lock.\n */\n #isUnlocked = false;\n\n /**\n * Cached decrypted vault data.\n *\n * This is used to cache the decrypted vault data to avoid decrypting the vault data multiple times.\n */\n #cachedDecryptedVaultData: DeserializedVaultData | undefined;\n\n /**\n * Creates a new SeedlessOnboardingController instance.\n *\n * @param options - The options for the SeedlessOnboardingController.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.encryptor - An optional encryptor to use for encrypting and decrypting seedless onboarding vault.\n * @param options.toprfKeyDeriver - An optional key derivation interface for the TOPRF client.\n * @param options.network - The network to be used for the Seedless Onboarding flow.\n * @param options.refreshJWTToken - A function to get a new jwt token using refresh token.\n * @param options.revokeRefreshToken - A function to revoke the refresh token.\n * @param options.renewRefreshToken - A function to renew the refresh token and get new revoke token.\n * @param options.passwordOutdatedCacheTTL - The TTL of the password outdated cache in milliseconds.,\n */\n constructor({\n messenger,\n state,\n encryptor,\n toprfKeyDeriver,\n network = Web3AuthNetwork.Mainnet,\n refreshJWTToken,\n revokeRefreshToken,\n renewRefreshToken,\n passwordOutdatedCacheTTL = PASSWORD_OUTDATED_CACHE_TTL_MS,\n }: SeedlessOnboardingControllerOptions<\n EncryptionKey,\n SupportedKeyDerivationOptions,\n EncryptionResult\n >) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: getInitialSeedlessOnboardingControllerStateWithDefaults(state),\n messenger,\n });\n\n assertIsPasswordOutdatedCacheValid(passwordOutdatedCacheTTL);\n this.#passwordOutdatedCacheTTL = passwordOutdatedCacheTTL;\n\n this.#vaultEncryptor = encryptor;\n\n this.toprfClient = new ToprfSecureBackup({\n network,\n keyDeriver: toprfKeyDeriver,\n fetchMetadataAccessCreds: this.fetchMetadataAccessCreds.bind(this),\n });\n this.#refreshJWTToken = refreshJWTToken;\n this.#revokeRefreshToken = revokeRefreshToken;\n this.#renewRefreshToken = renewRefreshToken;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n async fetchMetadataAccessCreds(): Promise<{\n metadataAccessToken: string;\n }> {\n const { metadataAccessToken } = this.state;\n if (!metadataAccessToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidMetadataAccessToken,\n );\n }\n\n // Use the same 90%-lifetime threshold as checkMetadataAccessTokenExpired\n // so both code paths agree on when a refresh is needed.\n const decodedToken = decodeJWTToken(metadataAccessToken);\n if (isTokenNearExpiry(decodedToken.exp, decodedToken.iat)) {\n // Token is near expiry or already expired, refresh it\n await this.refreshAuthTokens();\n\n // Get the new token after refresh\n const { metadataAccessToken: newMetadataAccessToken } = this.state;\n\n return {\n metadataAccessToken: newMetadataAccessToken as string,\n };\n }\n\n return { metadataAccessToken };\n }\n\n /**\n * Gets the node details for the TOPRF operations.\n * This function can be called to get the node endpoints, indexes and pubkeys and cache them locally.\n */\n async preloadToprfNodeDetails(): Promise<void> {\n try {\n await this.toprfClient.getNodeDetails();\n } catch {\n log('Failed to fetch node details');\n }\n }\n\n /**\n * Authenticate OAuth user using the seedless onboarding flow\n * and determine if the user is already registered or not.\n *\n * @param params - The parameters for authenticate OAuth user.\n * @param params.idTokens - The ID token(s) issued by OAuth verification service. Currently this array only contains a single idToken which is verified by all the nodes, in future we are considering to issue a unique idToken for each node.\n * @param params.authConnection - The social login provider.\n * @param params.authConnectionId - OAuth authConnectionId from dashboard\n * @param params.userId - user email or id from Social login\n * @param params.groupedAuthConnectionId - Optional grouped authConnectionId to be used for the authenticate request.\n * @param params.socialLoginEmail - The user email from Social login.\n * @param params.refreshToken - Refresh token issued during OAuth login. Written to state when provided.\n * @param params.revokeToken - revoke token for revoking refresh token and get new refresh token and new revoke token.\n * @param params.accessToken - Access token for pairing with profile sync auth service and to access other services.\n * @param params.metadataAccessToken - Metadata access token for accessing the metadata service before the vault is created or unlocked.\n * @param params.skipLock - Optional flag to skip acquiring the controller lock. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n refreshToken: string;\n revokeToken?: string;\n skipLock?: boolean;\n }): Promise<AuthenticateResult> {\n const doAuthenticateWithNodes = async (): Promise<AuthenticateResult> => {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n refreshToken,\n revokeToken,\n accessToken,\n metadataAccessToken,\n } = params;\n\n const authenticationResult = await this.toprfClient.authenticate({\n authConnectionId,\n userId,\n idTokens,\n groupedAuthConnectionId,\n });\n // update the state with the authenticated user info\n this.update((state) => {\n state.nodeAuthTokens = authenticationResult.nodeAuthTokens;\n state.authConnectionId = authConnectionId;\n state.groupedAuthConnectionId = groupedAuthConnectionId;\n state.userId = userId;\n state.authConnection = authConnection;\n state.socialLoginEmail = socialLoginEmail;\n state.metadataAccessToken = metadataAccessToken;\n state.refreshToken = refreshToken;\n if (revokeToken) {\n // Temporarily store revoke token & access token in state for later vault creation\n state.revokeToken = revokeToken;\n }\n state.accessToken = accessToken;\n\n // we will check if the controller state is properly set with the authenticated user info\n // before setting the isSeedlessOnboardingUserAuthenticated to true\n assertIsSeedlessOnboardingUserAuthenticated(state);\n state.isSeedlessOnboardingUserAuthenticated = true;\n });\n\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n };\n return params.skipLock\n ? await doAuthenticateWithNodes()\n : await this.#withControllerLock(doAuthenticateWithNodes);\n }\n\n /**\n * Create a new TOPRF encryption key using given password and backups the provided seed phrase.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @param seedPhrase - The initial seed phrase (Mnemonic) created together with the wallet.\n * @param keyringId - The keyring id of the backup seed phrase\n * @returns A promise that resolves to the encrypted seed phrase and the encryption key.\n */\n async createToprfKeyAndBackupSeedPhrase(\n password: string,\n seedPhrase: Uint8Array,\n keyringId: string,\n ): Promise<void> {\n return await this.#withControllerLock(async () => {\n // to make sure that fail fast,\n // assert that the user is authenticated before creating the TOPRF key and backing up the seed phrase\n this.#assertIsAuthenticatedUser(this.state);\n\n if (this.state.vault) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.VaultAlreadyExists,\n );\n }\n\n // locally evaluate the encryption key from the password\n const { encKey, pwEncKey, authKeyPair, oprfKey } =\n await this.toprfClient.createLocalKey({\n password,\n });\n const performKeyCreationAndBackup = async (): Promise<void> => {\n // encrypt and store the secret data\n const secretMetadata = await this.#encryptAndStoreSecretData({\n data: seedPhrase,\n dataType: EncAccountDataType.PrimarySrp,\n encKey,\n authKeyPair,\n options: {\n keyringId,\n },\n // Persist local backup state only after the full operation succeeds.\n skipStatePersist: true,\n });\n\n // store/persist the encryption key shares\n // We store the secret metadata in the metadata store first. If this operation fails,\n // we avoid persisting the encryption key shares to prevent a situation where a user appears\n // to have an account but with no associated data.\n await this.#persistOprfKey(oprfKey, authKeyPair.pk);\n // create a new vault with the resulting authentication data\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey as Uint8Array<ArrayBuffer>,\n rawToprfPwEncryptionKey: pwEncKey as Uint8Array<ArrayBuffer>,\n rawToprfAuthKeyPair: authKeyPair,\n });\n\n // Mark migration as complete since this new backup was created with the new data format (dataType)\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n\n // Persist local backup state after all operations succeed.\n this.#filterDupesAndUpdateSocialBackupsMetadata({\n keyringId,\n data: seedPhrase,\n type: secretMetadata.type,\n });\n };\n\n await this.#executeWithTokenRefresh(\n performKeyCreationAndBackup,\n 'createToprfKeyAndBackupSeedPhrase',\n );\n });\n }\n\n /**\n * Encrypt and add a new secret data to the metadata store.\n *\n * @param data - The data to add.\n * @param dataType - The data type classification for the secret data.\n * @param options - Optional options object, which includes optional data to be added to the metadata store.\n * @param options.keyringId - The keyring id of the backup keyring (SRP).\n * @returns A promise that resolves to the success of the operation.\n */\n async addNewSecretData(\n data: Uint8Array,\n dataType: EncAccountDataType,\n options?: {\n keyringId?: string;\n },\n ): Promise<void> {\n if (dataType === EncAccountDataType.PrimarySrp) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.PrimarySrpCannotBeAddedViaAddNewSecretData,\n );\n }\n\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n\n const performBackup = async (): Promise<void> => {\n await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n\n // verify the password and unlock the vault\n const { toprfEncryptionKey, toprfAuthKeyPair } =\n await this.#unlockVaultAndGetVaultData();\n\n // encrypt and store the secret data\n await this.#encryptAndStoreSecretData({\n data,\n dataType,\n encKey: toprfEncryptionKey,\n authKeyPair: toprfAuthKeyPair,\n options,\n });\n };\n\n await this.#executeWithTokenRefresh(performBackup, 'addNewSecretData');\n });\n }\n\n /**\n * Run any pending seedless onboarding migrations.\n *\n * This method should be called by clients after the controller is unlocked\n * to ensure legacy data is migrated to the latest format.\n *\n * Migrations are idempotent - running this multiple times is safe.\n * The migration version is tracked in state to prevent re-running migrations.\n *\n * @returns A promise that resolves to `true` if data was actually migrated\n * (items were updated on the server), `false` otherwise.\n * @throws If the password is outdated (changed on another device).\n */\n async runMigrations(): Promise<boolean> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n\n await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n\n if (this.state.migrationVersion < SeedlessOnboardingMigrationVersion.V1) {\n return this.#migrateDataTypes();\n }\n return false;\n });\n }\n\n /**\n * Set the migration version directly.\n *\n * Use this for new users who don't have legacy data to migrate,\n * avoiding an unnecessary API call from `runMigrations()`.\n *\n * @param version - The migration version to set.\n */\n setMigrationVersion(version: SeedlessOnboardingMigrationVersion): void {\n this.#setMigrationVersion(version);\n }\n\n /**\n * Assigns dataType (PrimarySrp/ImportedSrp/ImportedPrivateKey) to legacy secrets\n * that were created before the dataType field was introduced.\n *\n * This migration:\n * 1. Fetches all secret data items\n * 2. Identifies items that need migration (version !== 'v2' OR dataType not set)\n * 3. Assigns PrimarySrp to the first mnemonic (by timestamp)\n * 4. Assigns ImportedSrp to subsequent mnemonics\n * 5. Assigns ImportedPrivateKey to private keys\n * 6. Updates the items via SDK (which sets version to 'v2' and dataType)\n * 7. Updates the migration version in state\n *\n * Note: The SDK's updateSecretDataItem automatically sets version to 'v2'\n * when updating dataType, ensuring migrated items are marked as v2.\n *\n * @returns A promise that resolves to `true` if items were actually updated\n * on the server, `false` if no items needed migration.\n */\n async #migrateDataTypes(): Promise<boolean> {\n return await this.#executeWithTokenRefresh(async () => {\n const { toprfEncryptionKey, toprfAuthKeyPair } =\n await this.#unlockVaultAndGetVaultData();\n\n let secretDatas: SecretMetadata[];\n try {\n secretDatas = await this.#fetchAllSecretDataFromMetadataStore(\n toprfEncryptionKey,\n toprfAuthKeyPair,\n );\n } catch (error) {\n // If no secret data found, just update migration version\n if (\n error instanceof Error &&\n error.message ===\n SeedlessOnboardingControllerErrorMessage.NoSecretDataFound\n ) {\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n return false;\n }\n throw error;\n }\n\n const updates = getDataTypeMigrationUpdates(secretDatas);\n\n if (updates.length === 1) {\n await this.toprfClient.updateSecretDataItem({\n itemId: updates[0].itemId,\n dataType: updates[0].dataType,\n authKeyPair: toprfAuthKeyPair,\n });\n } else if (updates.length > 1) {\n await this.toprfClient.batchUpdateSecretDataItems({\n updateItems: updates,\n authKeyPair: toprfAuthKeyPair,\n });\n }\n\n this.#setMigrationVersion(SeedlessOnboardingMigrationVersion.V1);\n\n return updates.length > 0;\n }, 'migrateDataTypes');\n }\n\n /**\n * Set the migration version in state.\n *\n * @param version - The migration version to set.\n */\n #setMigrationVersion(version: number): void {\n this.update((state) => {\n state.migrationVersion = version;\n });\n }\n\n /**\n * Fetches all secret data items from the metadata store.\n *\n * Decrypts the secret data and returns the decrypted secret data using the recovered encryption key from the password.\n *\n * @param password - The optional password used to create new wallet. If not provided, `cached Encryption Key` will be used.\n * @returns A promise that resolves to the secret metadata items.\n */\n async fetchAllSecretData(password?: string): Promise<SecretMetadata[]> {\n return await this.#withControllerLock(async () => {\n return await this.#executeWithTokenRefresh(async () => {\n // assert that the user is authenticated before fetching the secret data\n this.#assertIsAuthenticatedUser(this.state);\n\n let encKey: Uint8Array;\n let pwEncKey: Uint8Array;\n let authKeyPair: KeyPair;\n\n if (password) {\n const recoverEncKeyResult = await this.#recoverEncKey(password);\n encKey = recoverEncKeyResult.encKey;\n pwEncKey = recoverEncKeyResult.pwEncKey;\n authKeyPair = recoverEncKeyResult.authKeyPair;\n } else {\n this.#assertIsUnlocked();\n // verify the password and unlock the vault\n const keysFromVault = await this.#unlockVaultAndGetVaultData();\n encKey = keysFromVault.toprfEncryptionKey;\n pwEncKey = keysFromVault.toprfPwEncryptionKey;\n authKeyPair = keysFromVault.toprfAuthKeyPair;\n }\n\n const secrets = await this.#fetchAllSecretDataFromMetadataStore(\n encKey,\n authKeyPair,\n );\n\n if (password) {\n // if password is provided, we need to create a new vault with the auth data. (supposedly the user is trying to rehydrate the wallet)\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey as Uint8Array<ArrayBuffer>,\n rawToprfPwEncryptionKey: pwEncKey as Uint8Array<ArrayBuffer>,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return secrets;\n }, 'fetchAllSecretData');\n });\n }\n\n /**\n * Update the password of the seedless onboarding flow.\n *\n * Changing password will also update the encryption key, metadata store and the vault with new encrypted values.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to the success of the operation.\n */\n async changePassword(\n newPassword: string,\n oldPassword: string,\n ): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n // verify the old password of the encrypted vault\n await this.verifyVaultPassword(oldPassword, {\n skipLock: true, // skip lock since we already have the lock\n });\n\n const attemptChangePassword = async (): Promise<void> => {\n const { latestKeyIndex } = await this.#assertPasswordInSync({\n skipCache: true,\n skipLock: true, // skip lock since we already have the lock\n });\n // load keyring encryption key if it exists\n let keyringEncryptionKey: string | undefined;\n if (this.state.encryptedKeyringEncryptionKey) {\n keyringEncryptionKey = await this.loadKeyringEncryptionKey();\n }\n\n // update the encryption key with new password and update the Metadata Store\n const {\n encKey: newEncKey,\n pwEncKey: newPwEncKey,\n authKeyPair: newAuthKeyPair,\n } = await this.#changeEncryptionKey({\n oldPassword,\n newPassword,\n latestKeyIndex,\n });\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey as Uint8Array<ArrayBuffer>,\n rawToprfPwEncryptionKey: newPwEncKey as Uint8Array<ArrayBuffer>,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n\n this.#resetPasswordOutdatedCache();\n\n // store the keyring encryption key if it exists\n if (keyringEncryptionKey) {\n await this.storeKeyringEncryptionKey(keyringEncryptionKey);\n }\n };\n\n try {\n await this.#executeWithTokenRefresh(\n attemptChangePassword,\n 'changePassword',\n );\n } catch (error) {\n log('Error changing password', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToChangePassword,\n {\n cause: error,\n },\n );\n }\n });\n }\n\n /**\n * Update the backup metadata state for the given secret data.\n *\n * @param secretData - The data to backup, can be a single backup or array of backups.\n * @param secretData.keyringId - The keyring id associated with the backup secret data.\n * @param secretData.data - The secret data to update the backup metadata state.\n */\n updateBackupMetadataState(\n secretData:\n | (Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array })\n | (Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array })[],\n ): void {\n this.#assertIsUnlocked();\n\n this.#filterDupesAndUpdateSocialBackupsMetadata(secretData);\n }\n\n /**\n * Verify the password validity by decrypting the vault.\n *\n * @param password - The password to verify.\n * @param options - Optional options object.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to the success of the operation.\n * @throws {Error} If the password is invalid or the vault is not initialized.\n */\n async verifyVaultPassword(\n password: string,\n options?: {\n skipLock?: boolean;\n },\n ): Promise<void> {\n const doVerify = async (): Promise<void> => {\n if (!this.state.vault) {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultError);\n }\n await this.#vaultEncryptor.decrypt(password, this.state.vault);\n };\n return options?.skipLock\n ? await doVerify()\n : await this.#withControllerLock(doVerify);\n }\n\n /**\n * Get backup state of the given secret data, from the controller state.\n *\n * If the given secret data is not backed up and not found in the state, it will return `undefined`.\n *\n * @param data - The data to get the backup state of.\n * @param type - The type of the secret data.\n * @returns The backup state of the given secret data.\n */\n getSecretDataBackupState(\n data: Uint8Array,\n type: SecretType = SecretType.Mnemonic,\n ): SocialBackupsMetadata | undefined {\n const secretDataHash = keccak256AndHexify(data);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === secretDataHash && backup.type === type,\n );\n }\n\n /**\n * Submit the password to the controller, verify the password validity and unlock the controller.\n *\n * This method will be used especially when user unlock the wallet.\n * The provided password will be verified against the encrypted vault, encryption key will be derived and saved in the controller state.\n *\n * This operation is useful when user performs some actions that requires the user password/encryption key. e.g. add new srp backup\n *\n * @param password - The password to submit.\n * @returns A promise that resolves to the success of the operation.\n */\n async submitPassword(password: string): Promise<void> {\n return await this.#withControllerLock(async () => {\n // get the access token from the state before unlocking, it might be the new token set from the `refreshAuthTokens` method.\n const { accessToken: accessTokenBeforeUnlock } = this.state;\n\n const deserializedVaultData = await this.#unlockVaultAndGetVaultData({\n password,\n });\n\n const accessTokenFromDecryptedVault = deserializedVaultData.accessToken;\n\n // Pick the latest access token - the token from state might be newer (from refreshAuthTokens)\n // than the token stored in the vault.\n const latestAccessToken = this.#pickLatestAccessToken(\n accessTokenBeforeUnlock,\n accessTokenFromDecryptedVault,\n );\n\n // update the state and vault with the latest access token `ONLY` if it's different from the current access token in the state.\n if (latestAccessToken !== accessTokenFromDecryptedVault) {\n const updatedVaultData = {\n ...deserializedVaultData,\n accessToken: latestAccessToken,\n };\n\n await this.#updateVault({\n password,\n vaultData: updatedVaultData,\n pwEncKey: deserializedVaultData.toprfPwEncryptionKey,\n });\n }\n\n this.#setUnlocked();\n\n this.#identifyIncompleteMetadataBackup(password);\n });\n }\n\n /**\n * Identify an incomplete or mismatched primary SRP backup.\n *\n * This method must only be called after the controller has been unlocked.\n *\n * @param password - The password used to export the local primary SRP.\n * @returns A promise that resolves after identification and telemetry have\n * completed.\n */\n async identifyIncompleteMetadataBackup(password: string): Promise<void> {\n this.#assertIsUnlocked();\n\n await this.#identifyIncompleteMetadataBackup(password);\n }\n\n /**\n * Set the controller to locked state, and deallocate the secrets (vault encryption key and salt).\n *\n * When the controller is locked, the user will not be able to perform any operations on the controller/vault.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async setLocked(): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.update((state) => {\n delete state.vaultEncryptionKey;\n delete state.vaultEncryptionSalt;\n delete state.revokeToken;\n delete state.accessToken;\n });\n\n this.#cachedDecryptedVaultData = undefined;\n this.#isUnlocked = false;\n });\n }\n\n /**\n * Sync the latest global password to the controller.\n * reset vault with latest globalPassword,\n * persist the latest global password authPubKey\n *\n * @param params - The parameters for syncing the latest global password.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the success of the operation.\n */\n async syncLatestGlobalPassword({\n globalPassword,\n }: {\n globalPassword: string;\n }): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsUnlocked();\n const doSyncPassword = async (): Promise<void> => {\n // update vault with latest globalPassword\n const { encKey, pwEncKey, authKeyPair } =\n await this.#recoverEncKey(globalPassword);\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: globalPassword,\n rawToprfEncryptionKey: encKey as Uint8Array<ArrayBuffer>,\n rawToprfPwEncryptionKey: pwEncKey as Uint8Array<ArrayBuffer>,\n rawToprfAuthKeyPair: authKeyPair,\n });\n\n this.#resetPasswordOutdatedCache();\n };\n return await this.#executeWithTokenRefresh(\n doSyncPassword,\n 'syncLatestGlobalPassword',\n );\n });\n }\n\n /**\n * @description Unlock the controller with the latest global password.\n *\n * @param params - The parameters for unlocking the controller.\n * @param params.maxKeyChainLength - The maximum chain length of the pwd encryption keys.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the success of the operation.\n */\n async submitGlobalPassword({\n globalPassword,\n maxKeyChainLength = 5,\n }: {\n globalPassword: string;\n maxKeyChainLength?: number;\n }): Promise<void> {\n return await this.#withControllerLock(async () => {\n return await this.#executeWithTokenRefresh(async () => {\n const currentDeviceAuthPubKey = this.#recoverAuthPubKey();\n await this.#submitGlobalPassword({\n targetAuthPubKey: currentDeviceAuthPubKey,\n globalPassword,\n maxKeyChainLength,\n });\n }, 'submitGlobalPassword');\n });\n }\n\n /**\n * @description Submit the global password to the controller, verify the\n * password validity and unlock the controller.\n *\n * @param params - The parameters for submitting the global password.\n * @param params.maxKeyChainLength - The maximum chain length of the pwd encryption keys.\n * @param params.targetAuthPubKey - The target public key of the keyring\n * encryption key to recover.\n * @param params.globalPassword - The latest global password.\n * @returns A promise that resolves to the keyring encryption key\n * corresponding to the current authPubKey in state.\n */\n async #submitGlobalPassword({\n targetAuthPubKey,\n globalPassword,\n maxKeyChainLength,\n }: {\n targetAuthPubKey: SEC1EncodedPublicKey;\n globalPassword: string;\n maxKeyChainLength: number;\n }): Promise<void> {\n const { pwEncKey: globalPwEncKey, authKeyPair: globalAuthKeyPair } =\n await this.#recoverEncKey(globalPassword);\n\n try {\n // Recover vault encryption key.\n const res = await this.toprfClient.recoverPwEncKey({\n targetAuthPubKey,\n curPwEncKey: globalPwEncKey,\n curAuthKeyPair: globalAuthKeyPair,\n maxPwChainLength: maxKeyChainLength,\n });\n const { pwEncKey } = res;\n const vaultKey = await this.#loadSeedlessEncryptionKey(\n pwEncKey as Uint8Array<ArrayBuffer>,\n );\n\n // accessToken before unlocking vault and flooding the state with values from the decrypted vault\n // it might be the new token set from the `refreshAuthTokens` method.\n const { accessToken: accessTokenBeforeUnlock } = this.state;\n\n // Unlock the controller\n const decryptedVaultData = await this.#unlockVaultAndGetVaultData({\n encryptionKey: vaultKey,\n });\n this.#setUnlocked();\n\n // Pick the latest access token - the token from state might be newer (from refreshAuthTokens)\n // than the token stored in the vault. The vault will be updated later by syncLatestGlobalPassword.\n this.#pickLatestAccessToken(\n accessTokenBeforeUnlock,\n decryptedVaultData.accessToken,\n );\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n if (isMaxKeyChainLengthError(error)) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MaxKeyChainLengthExceeded,\n );\n }\n throw PasswordSyncError.getInstance(error);\n }\n }\n\n /**\n * @description Check if the current password is outdated compare to the global password.\n *\n * @param options - Optional options object.\n * @param options.globalAuthPubKey - The global auth public key to compare with the current auth public key.\n * If not provided, the global auth public key will be fetched from the backend.\n * @param options.skipCache - If true, bypass the cache and force a fresh check.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns A promise that resolves to true if the password is outdated, false otherwise.\n */\n async checkIsPasswordOutdated(options?: {\n skipCache?: boolean;\n skipLock?: boolean;\n globalAuthPubKey?: SEC1EncodedPublicKey;\n }): Promise<boolean> {\n const doCheckIsPasswordExpired = async (): Promise<boolean> => {\n // cache result to reduce load on infra\n // Check cache first unless skipCache is true\n if (!options?.skipCache) {\n const { passwordOutdatedCache } = this.state;\n const now = Date.now();\n const isCacheValid =\n passwordOutdatedCache &&\n now - passwordOutdatedCache.timestamp <\n this.#passwordOutdatedCacheTTL;\n\n if (isCacheValid) {\n return passwordOutdatedCache.isExpiredPwd;\n }\n }\n\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n const currentDeviceAuthPubKey = this.#recoverAuthPubKey();\n\n let globalAuthPubKey = options?.globalAuthPubKey;\n if (!globalAuthPubKey) {\n const { authPubKey } = await this.toprfClient\n .fetchAuthPubKey({\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n })\n .catch((error) => {\n log('Error fetching auth pub key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchAuthPubKey,\n {\n cause: error,\n },\n );\n });\n globalAuthPubKey = authPubKey;\n }\n\n // use noble lib to deserialize and compare curve point\n const isExpiredPwd = !secp256k1.ProjectivePoint.fromHex(\n currentDeviceAuthPubKey,\n ).equals(secp256k1.ProjectivePoint.fromHex(globalAuthPubKey));\n // Cache the result in state\n this.update((state) => {\n state.passwordOutdatedCache = { isExpiredPwd, timestamp: Date.now() };\n });\n return isExpiredPwd;\n };\n\n return await this.#executeWithTokenRefresh(\n async () =>\n options?.skipLock\n ? await doCheckIsPasswordExpired()\n : await this.#withControllerLock(doCheckIsPasswordExpired),\n 'checkIsPasswordOutdated',\n );\n }\n\n /**\n * Check if the user is authenticated with the seedless onboarding flow by checking the token values in the state.\n *\n * This method will check the `accessToken` and `revokeToken` in the state, besides the social login authentication details.\n * If both are present, the user is authenticated.\n * If either is missing, the user is not authenticated.\n *\n * This method is useful when we want to check if the state has valid authenticated user details to perform vault creations.\n *\n * @returns True if the user is authenticated, false otherwise.\n */\n async getIsUserAuthenticated(): Promise<boolean> {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n return Boolean(this.state.accessToken) && Boolean(this.state.revokeToken);\n } catch {\n return false;\n }\n }\n\n #setUnlocked(): void {\n this.#isUnlocked = true;\n }\n\n /**\n * Compares two access tokens and picks the latest one based on JWT expiration.\n * If the tokens are different, the state is updated with the latest token.\n *\n * @param tokenBeforeUnlock - The access token from state before unlocking (may have been set by refreshAuthTokens).\n * @param tokenAfterUnlock - The access token from the decrypted vault after unlocking.\n * @returns The latest access token, or the token after unlock if no reconciliation was needed.\n */\n #pickLatestAccessToken(\n tokenBeforeUnlock: string | undefined,\n tokenAfterUnlock: string,\n ): string {\n let latestToken = tokenAfterUnlock;\n\n if (\n tokenBeforeUnlock &&\n tokenAfterUnlock &&\n tokenBeforeUnlock !== tokenAfterUnlock\n ) {\n latestToken = compareAndGetLatestToken(\n tokenBeforeUnlock,\n tokenAfterUnlock,\n );\n\n // Update the access token in the state with the latest access token\n this.update((state) => {\n state.accessToken = latestToken;\n });\n }\n\n return latestToken;\n }\n\n /**\n * Clears the current state of the SeedlessOnboardingController.\n */\n clearState(): void {\n const defaultState =\n getInitialSeedlessOnboardingControllerStateWithDefaults();\n this.update(() => {\n return defaultState;\n });\n }\n\n /**\n * Persist the encryption key for the seedless onboarding flow.\n *\n * @param oprfKey - The OPRF key to be splited and persisted.\n * @param authPubKey - The authentication public key.\n * @returns A promise that resolves to the success of the operation.\n */\n async #persistOprfKey(\n oprfKey: bigint,\n authPubKey: SEC1EncodedPublicKey,\n ): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n const { authConnectionId, groupedAuthConnectionId, userId } = this.state;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n log('Error persisting local encryption key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToPersistOprfKey,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Persist the authentication public key for the seedless onboarding flow.\n * convert to suitable format before persisting.\n *\n * @param params - The parameters for persisting the authentication public key.\n * @param params.authPubKey - The authentication public key to be persisted.\n */\n #persistAuthPubKey(params: { authPubKey: SEC1EncodedPublicKey }): void {\n this.update((state) => {\n state.authPubKey = bytesToBase64(params.authPubKey);\n });\n }\n\n /**\n * Store the keyring encryption key in state, encrypted under the current\n * encryption key.\n *\n * @param keyringEncryptionKey - The keyring encryption key.\n */\n async storeKeyringEncryptionKey(keyringEncryptionKey: string): Promise<void> {\n const { toprfPwEncryptionKey: encKey } =\n await this.#unlockVaultAndGetVaultData();\n await this.#storeKeyringEncryptionKey(encKey, keyringEncryptionKey);\n }\n\n /**\n * Load the keyring encryption key from state, decrypted under the current\n * encryption key.\n *\n * @returns The keyring encryption key.\n */\n async loadKeyringEncryptionKey(): Promise<string> {\n const { toprfPwEncryptionKey: encKey } =\n await this.#unlockVaultAndGetVaultData();\n return await this.#loadKeyringEncryptionKey(encKey);\n }\n\n /**\n * Encrypt the keyring encryption key and store it in state.\n *\n * @param encKey - The encryption key.\n * @param keyringEncryptionKey - The keyring encryption key.\n */\n async #storeKeyringEncryptionKey(\n encKey: Uint8Array<ArrayBuffer>,\n keyringEncryptionKey: string,\n ): Promise<void> {\n const { ciphertext, iv } = await encrypt(\n encKey,\n stringToBytes(keyringEncryptionKey),\n );\n const encryptedKeyringEncryptionKey = concatBytes([iv, ciphertext]);\n this.update((state) => {\n state.encryptedKeyringEncryptionKey = bytesToBase64(\n encryptedKeyringEncryptionKey,\n );\n });\n }\n\n /**\n * Decrypt the keyring encryption key from state.\n *\n * @param encKey - The encryption key.\n * @returns The keyring encryption key.\n */\n async #loadKeyringEncryptionKey(\n encKey: Uint8Array<ArrayBuffer>,\n ): Promise<string> {\n const { encryptedKeyringEncryptionKey: encryptedKey } = this.state;\n assertIsEncryptedKeyringEncryptionKeySet(encryptedKey);\n const encryptedPasswordBytes = base64ToBytes(encryptedKey);\n const iv = encryptedPasswordBytes.slice(0, IV_LENGTH);\n const ciphertext = encryptedPasswordBytes.slice(IV_LENGTH);\n const password = await decrypt(encKey, iv, ciphertext);\n return bytesToString(password);\n }\n\n /**\n * Decrypt the seedless encryption key from state.\n *\n * @param encKey - The encryption key.\n * @returns The seedless encryption key.\n */\n async #loadSeedlessEncryptionKey(\n encKey: Uint8Array<ArrayBuffer>,\n ): Promise<string> {\n const { encryptedSeedlessEncryptionKey: encryptedKey } = this.state;\n assertIsEncryptedSeedlessEncryptionKeySet(encryptedKey);\n const encryptedKeyBytes = base64ToBytes(encryptedKey);\n const iv = encryptedKeyBytes.slice(0, IV_LENGTH);\n const ciphertext = encryptedKeyBytes.slice(IV_LENGTH);\n const seedlessEncryptionKey = await decrypt(encKey, iv, ciphertext);\n return bytesToString(seedlessEncryptionKey);\n }\n\n /**\n * Recover the authentication public key from the state.\n * convert to pubkey format before recovering.\n *\n * @returns The authentication public key.\n */\n #recoverAuthPubKey(): SEC1EncodedPublicKey {\n const { authPubKey } = this.state;\n if (!authPubKey) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.SRPNotBackedUpError,\n );\n }\n\n return base64ToBytes(authPubKey);\n }\n\n /**\n * Recover the encryption key from password.\n *\n * @param password - The password used to derive/recover the encryption key.\n * @returns A promise that resolves to the encryption key and authentication key pair.\n * @throws RecoveryError - If failed to recover the encryption key.\n */\n async #recoverEncKey(\n password: string,\n ): Promise<Omit<RecoverEncryptionKeyResult, 'rateLimitResetResult'>> {\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens,\n password,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n // throw token expired error for token refresh handler\n if (isAuthTokenError(error)) {\n throw error;\n }\n\n throw RecoveryError.getInstance(error);\n }\n }\n\n async #fetchAllSecretDataFromMetadataStore(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): Promise<SecretMetadata[]> {\n let secretDataItems: FetchedSecretDataItem[] = [];\n try {\n // fetch and decrypt the secret data from the metadata store\n secretDataItems = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n } catch (error) {\n log('Error fetching secret data', error);\n if (isAuthTokenError(error)) {\n throw error;\n }\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchSecretMetadata,\n {\n cause: error,\n },\n );\n }\n\n // user must have at least one secret data\n if (secretDataItems?.length > 0) {\n return parseAndValidateSecretMetadataBackup(secretDataItems);\n }\n\n throw new Error(SeedlessOnboardingControllerErrorMessage.NoSecretDataFound);\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param params - The function parameters.\n * @param params.oldPassword - The old password to verify.\n * @param params.newPassword - The new password to update.\n * @param params.latestKeyIndex - The key index of the latest key.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey({\n oldPassword,\n newPassword,\n latestKeyIndex,\n }: {\n newPassword: string;\n oldPassword: string;\n latestKeyIndex?: number;\n }): Promise<ChangeEncryptionKeyResult> {\n this.#assertIsAuthenticatedUser(this.state);\n const { authConnectionId, groupedAuthConnectionId, userId } = this.state;\n\n let encKey: Uint8Array;\n let pwEncKey: Uint8Array;\n let authKeyPair: KeyPair;\n let globalKeyIndex = latestKeyIndex;\n if (globalKeyIndex) {\n ({\n toprfEncryptionKey: encKey,\n toprfPwEncryptionKey: pwEncKey,\n toprfAuthKeyPair: authKeyPair,\n } = await this.#unlockVaultAndGetVaultData({ password: oldPassword }));\n } else {\n ({\n encKey,\n pwEncKey,\n authKeyPair,\n keyShareIndex: globalKeyIndex,\n } = await this.#recoverEncKey(oldPassword));\n }\n const result = await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n oldEncKey: encKey,\n oldPwEncKey: pwEncKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex: globalKeyIndex,\n newPassword,\n transformDataItems: (items) =>\n items\n .sort((a, b) =>\n SecretMetadata.compare(\n SecretMetadata.fromRawMetadata(a.data, { dataType: a.dataType }),\n SecretMetadata.fromRawMetadata(b.data, { dataType: b.dataType }),\n 'asc',\n ),\n )\n .map(({ data, dataType, version }) => ({\n data,\n dataType,\n version: dataType === undefined ? 'v1' : version,\n })),\n });\n return result;\n }\n\n /**\n * Encrypt and store the secret data backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the secret data backup.\n * @param params.data - The secret data to store.\n * @param params.dataType - The data type classification for the secret data.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n * @param params.options - Optional options object.\n * @param params.options.keyringId - The keyring id of the backup keyring (required for SRP types).\n * @param params.skipStatePersist - Whether to persist the backup state after\n * the remote metadata is stored. When true, the backup metadata is not persisted to the controller state.\n *\n * @returns A promise that resolves to the backup metadata.\n */\n async #encryptAndStoreSecretData(params: {\n data: Uint8Array;\n dataType: EncAccountDataType;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n options?: {\n keyringId?: string;\n };\n skipStatePersist?: boolean;\n }): Promise<SecretMetadata> {\n const {\n options,\n data,\n encKey,\n authKeyPair,\n dataType,\n skipStatePersist = false,\n } = params;\n\n const secretMetadata = new SecretMetadata(data, { dataType });\n const { type } = secretMetadata;\n\n // before encrypting and create backup, we will check the state if the secret data is already backed up\n const backupState = this.getSecretDataBackupState(data, type);\n if (backupState) {\n return secretMetadata;\n }\n\n const secretData = secretMetadata.toBytes();\n\n const keyringId = options?.keyringId as string;\n if (type === SecretType.Mnemonic && !keyringId) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MissingKeyringId,\n );\n }\n\n try {\n const persistMetadataFn = async (): Promise<\n Omit<SocialBackupsMetadata, 'hash'> & { data: Uint8Array }\n > => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n dataType,\n });\n return {\n keyringId,\n data,\n type,\n };\n };\n\n // Skip local persistence if `skipStatePersist` is true.\n if (skipStatePersist) {\n await persistMetadataFn();\n } else {\n await this.#withPersistedSecretMetadataBackupsState(persistMetadataFn);\n }\n\n return secretMetadata;\n } catch (error) {\n if (isAuthTokenError(error)) {\n throw error;\n }\n log('Error encrypting and storing secret data backup', error);\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.FailedToEncryptAndStoreSecretData,\n );\n }\n }\n\n /**\n * Unlocks the encrypted vault using the provided password and returns the decrypted vault data.\n * This method ensures thread-safety by using a mutex lock when accessing the vault.\n *\n * @param params - The parameters for unlocking the vault.\n * @param params.password - The optional password to unlock the vault.\n * @param params.encryptionKey - The optional encryption key to unlock the vault.\n * @returns A promise that resolves to an object containing:\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\n * - revokeToken: The decrypted revoke token\n * - accessToken: The decrypted access token\n * @throws {Error} If:\n * - The password is invalid or empty\n * - The vault is not initialized\n * - The password is incorrect (from encryptor.decrypt)\n * - The decrypted vault data is malformed\n */\n async #unlockVaultAndGetVaultData(params?: {\n password?: string;\n encryptionKey?: string;\n }): Promise<DeserializedVaultData> {\n return this.#withVaultLock(async () => {\n if (this.#cachedDecryptedVaultData) {\n return this.#cachedDecryptedVaultData;\n }\n\n const { vaultData, vaultEncryptionKey, vaultEncryptionSalt } =\n await this.#decryptAndParseVaultData(params);\n\n this.update((state) => {\n state.vaultEncryptionKey = vaultEncryptionKey;\n state.vaultEncryptionSalt = vaultEncryptionSalt;\n state.revokeToken = vaultData.revokeToken;\n state.accessToken = vaultData.accessToken;\n });\n\n const deserializedVaultData = deserializeVaultData(vaultData);\n this.#cachedDecryptedVaultData = deserializedVaultData;\n return deserializedVaultData;\n });\n }\n\n /**\n * Decrypts the vault data and parses it into a usable format.\n *\n * @param params - The parameters for decrypting the vault.\n * @param params.password - The optional password to decrypt the vault.\n * @param params.encryptionKey - The optional encryption key to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n */\n async #decryptAndParseVaultData(params?: {\n password?: string;\n encryptionKey?: string;\n }): Promise<{\n vaultData: VaultData;\n vaultEncryptionKey: string;\n vaultEncryptionSalt?: string;\n }> {\n let { vaultEncryptionKey, vaultEncryptionSalt } = this.state;\n const { vault: encryptedVault } = this.state;\n\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultError);\n }\n\n if (params?.encryptionKey) {\n vaultEncryptionKey = params.encryptionKey;\n }\n\n let decryptedVaultData: unknown;\n\n // if the encryption key is available, we will use it to decrypt the vault\n if (vaultEncryptionKey) {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (\n vaultEncryptionSalt &&\n vaultEncryptionSalt !== parsedEncryptedVault.salt\n ) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.ExpiredCredentials,\n );\n }\n\n const key = await this.#vaultEncryptor.importKey(vaultEncryptionKey);\n decryptedVaultData = await this.#vaultEncryptor.decryptWithKey(\n key,\n parsedEncryptedVault,\n );\n } else {\n // if the encryption key is not available, we will use the password to decrypt the vault\n assertIsValidPassword(params?.password);\n // Note that vault decryption using the password is a very costly operation as it involves deriving the encryption key\n // from the password using an intentionally slow key derivation function.\n // We should make sure that we only call it very intentionally.\n const result = await this.#vaultEncryptor.decryptWithDetail(\n params.password,\n encryptedVault,\n );\n decryptedVaultData = result.vault;\n vaultEncryptionKey = result.exportedKeyString;\n vaultEncryptionSalt = result.salt;\n }\n\n const vaultData = parseVaultData(decryptedVaultData);\n\n return {\n vaultData,\n vaultEncryptionKey,\n vaultEncryptionSalt,\n };\n }\n\n /**\n * Executes a callback function that creates or restores secret data and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore secret data\n * 2. Generates keccak256 hashes of the secret data\n * 3. Merges new hashes with existing ones in the state, ensuring uniqueness\n * 4. Updates the controller state with the combined hashes\n *\n * This is a wrapper method that should be used around any operation that creates\n * or restores secret data to ensure their hashes are properly tracked.\n *\n * @param createSecretMetadataBackupCallback - function that returns either a single secret data\n * or an array of secret data as Uint8Array(s)\n * @returns The original secret data(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSecretMetadataBackupsState(\n createSecretMetadataBackupCallback: () => Promise<SecretBackupData>,\n ): Promise<SecretBackupData> {\n try {\n const newBackup = await createSecretMetadataBackupCallback();\n\n this.#filterDupesAndUpdateSocialBackupsMetadata(newBackup);\n\n return newBackup;\n } catch (error) {\n log('Error persisting secret data backups', error);\n throw error;\n }\n }\n\n /**\n * Updates the social backups metadata state by adding new unique secret data backups.\n * This method ensures no duplicate backups are stored by checking the hash of each secret data.\n *\n * @param secretData - The backup data to add to the state\n * @param secretData.data - The secret data to backup as a Uint8Array\n * @param secretData.keyringId - The optional keyring id of the backup keyring (SRP).\n * @param secretData.type - The type of the secret data.\n */\n #filterDupesAndUpdateSocialBackupsMetadata(\n secretData: SecretBackupData | SecretBackupData[],\n ): void {\n const filteredNewBackupsMetadata = getNewSocialBackupsMetadata(\n this.state.socialBackupsMetadata,\n secretData,\n );\n\n if (filteredNewBackupsMetadata.length > 0) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n ...filteredNewBackupsMetadata,\n ];\n });\n }\n }\n\n /**\n * Create a new vault with the given authentication data.\n *\n * Serialize the authentication and key data which will be stored in the vault.\n *\n * @param params - The parameters for creating a new vault.\n * @param params.password - The password to encrypt the vault.\n * @param params.rawToprfEncryptionKey - The encryption key to encrypt the vault.\n * @param params.rawToprfPwEncryptionKey - The encryption key to encrypt the password.\n * @param params.rawToprfAuthKeyPair - The authentication key pair for Toprf operations.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfPwEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array<ArrayBuffer>;\n rawToprfPwEncryptionKey: Uint8Array<ArrayBuffer>;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { accessToken, revokeToken } =\n await this.#getAccessTokenAndRevokeToken(password);\n\n const vaultData: DeserializedVaultData = {\n toprfAuthKeyPair: rawToprfAuthKeyPair,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfPwEncryptionKey: rawToprfPwEncryptionKey,\n revokeToken,\n accessToken,\n };\n\n await this.#updateVault({\n password,\n vaultData,\n pwEncKey: rawToprfPwEncryptionKey,\n });\n\n // update the authPubKey in the state\n this.#persistAuthPubKey({\n authPubKey: rawToprfAuthKeyPair.pk,\n });\n\n this.#setUnlocked();\n }\n\n /**\n * Encrypt and update the vault with the given authentication data.\n *\n * @param params - The parameters for updating the vault.\n * @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.\n * @param params.vaultData - The raw vault data to update the vault with.\n * @param params.pwEncKey - The global password encryption key.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n vaultData,\n pwEncKey,\n }: {\n password?: string;\n vaultData: DeserializedVaultData;\n pwEncKey: Uint8Array<ArrayBuffer>;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n const serializedVaultData = serializeVaultData(vaultData);\n\n const { vaultEncryptionKey, vaultEncryptionSalt, vault } = this.state;\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {\n vault,\n vaultEncryptionKey,\n vaultEncryptionSalt,\n encryptedSeedlessEncryptionKey:\n this.state.encryptedSeedlessEncryptionKey,\n };\n\n // if the password is provided (not undefined), encrypt the vault with the password\n // We gonna prioritize the password encryption here, in case of the operation is `Change Password`.\n // We don't wanna re-use the old encryption key from the state.\n if (password !== undefined) {\n assertIsValidPassword(password);\n\n // Note that vault encryption using the password is a very costly operation as it involves deriving the encryption key\n // from the password using an intentionally slow key derivation function.\n // We should make sure that we only call it very intentionally.\n const { vault: updatedEncVault, exportedKeyString } =\n await this.#vaultEncryptor.encryptWithDetail(\n password,\n serializedVaultData,\n );\n\n updatedState.vault = updatedEncVault;\n updatedState.vaultEncryptionKey = exportedKeyString;\n updatedState.vaultEncryptionSalt = JSON.parse(updatedEncVault).salt;\n\n // encrypt the seedless encryption key with the password encryption key from TOPRF network\n updatedState.encryptedSeedlessEncryptionKey =\n await this.#encryptSeedlessEncryptionKey(exportedKeyString, pwEncKey);\n } else if (vaultEncryptionKey && vaultEncryptionSalt) {\n const encryptionKey =\n await this.#vaultEncryptor.importKey(vaultEncryptionKey);\n const updatedEncVault = await this.#vaultEncryptor.encryptWithKey(\n encryptionKey,\n serializedVaultData,\n );\n\n // NOTE: Referenced from keyring-controller!\n // We need to include the salt used to derive the encryption key, to be able to derive it from password again.\n updatedEncVault.salt = vaultEncryptionSalt;\n\n updatedState.vault = JSON.stringify(updatedEncVault);\n updatedState.vaultEncryptionKey = vaultEncryptionKey;\n updatedState.vaultEncryptionSalt = vaultEncryptionSalt;\n } else {\n // neither password nor encryption key is provided\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.MissingCredentials,\n );\n }\n\n // update the state with the updated vault data\n this.update((state) => {\n state.vault = updatedState.vault;\n state.vaultEncryptionKey = updatedState.vaultEncryptionKey;\n state.vaultEncryptionSalt = updatedState.vaultEncryptionSalt;\n state.encryptedSeedlessEncryptionKey =\n updatedState.encryptedSeedlessEncryptionKey;\n });\n\n // cache the vault data to avoid decrypting the vault data multiple times\n this.#cachedDecryptedVaultData = vaultData;\n });\n }\n\n /**\n * Encrypt the seedless encryption key with the password encryption key from TOPRF network.\n *\n * @param vaultEncryptionKey - The key which is used to encrypt the vault.\n * @param pwEncKey - The password encryption key from TOPRF network.\n * @returns The encrypted seedless encryption key.\n */\n async #encryptSeedlessEncryptionKey(\n vaultEncryptionKey: string,\n pwEncKey: Uint8Array<ArrayBuffer>,\n ): Promise<string> {\n const { ciphertext, iv } = await encrypt(\n pwEncKey,\n stringToBytes(vaultEncryptionKey),\n );\n return bytesToBase64(concatBytes([iv, ciphertext]));\n }\n\n /**\n * Get the access token and revoke token from the state or the vault.\n *\n * @param password - The password to decrypt the vault.\n * @returns The access token and revoke token.\n */\n async #getAccessTokenAndRevokeToken(\n password: string,\n ): Promise<{ accessToken: string; revokeToken: string }> {\n let { accessToken, revokeToken } = this.state;\n // `accessToken` and `revokeToken` are both available in the state, `ONLY` when the wallet (vault) is unlocked\n // or during the period between the social authentication and the vault creation during the onboarding flow.\n if (accessToken && revokeToken) {\n return { accessToken, revokeToken };\n }\n\n // if `password` is provided to decrypt the vault, decrypt the vault and get the access token and revoke token from the vault\n if (this.state.vault) {\n // if the access token or revoke token is not available in the state, decrypt the vault and get the access token and revoke token from the vault\n const { vaultData } = await this.#decryptAndParseVaultData({ password });\n accessToken = accessToken ?? vaultData.accessToken;\n revokeToken = revokeToken ?? vaultData.revokeToken;\n }\n\n // we should always throw an error if the access token or revoke token is not available\n // to prevent the caller from using the controller in an invalid state\n\n if (!accessToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidAccessToken,\n );\n }\n\n if (!revokeToken) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidRevokeToken,\n );\n }\n\n return { accessToken, revokeToken };\n }\n\n /**\n * Lock the controller mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * This wrapper ensures that each mutable operation that interacts with the\n * controller and that changes its state is executed in a mutually exclusive way,\n * preventing unsafe concurrent access that could lead to unpredictable behavior.\n *\n * @param callback - The function to execute while the controller mutex is locked.\n * @returns The result of the function.\n */\n async #withControllerLock<Result>(\n callback: MutuallyExclusiveCallback<Result>,\n ): Promise<Result> {\n return await withLock(this.#controllerOperationMutex, callback);\n }\n\n /**\n * Lock the vault mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * This ensures that each operation that interacts with the vault\n * is executed in a mutually exclusive way.\n *\n * @param callback - The function to execute while the vault mutex is locked.\n * @returns The result of the function.\n */\n async #withVaultLock<Result>(\n callback: MutuallyExclusiveCallback<Result>,\n ): Promise<Result> {\n return await withLock(this.#vaultOperationMutex, callback);\n }\n\n #assertIsUnlocked(): void {\n if (!this.#isUnlocked) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.ControllerLocked,\n );\n }\n }\n\n /**\n * Assert that the provided value contains valid authenticated user information.\n *\n * This method checks that the value is an object containing:\n * - nodeAuthTokens: A non-empty array of authentication tokens\n * - authConnectionId: A string identifier for the OAuth connection\n * - groupedAuthConnectionId: A string identifier for grouped OAuth connections\n * - userId: A string identifier for the authenticated user\n *\n * @param value - The value to validate.\n * @throws {Error} If the value does not contain valid authenticated user information.\n */\n #assertIsAuthenticatedUser(\n value: unknown,\n ): asserts value is AuthenticatedUserDetails {\n try {\n assertIsSeedlessOnboardingUserAuthenticated(value);\n } catch (error) {\n this.update((state) => {\n state.isSeedlessOnboardingUserAuthenticated = false;\n });\n throw error;\n }\n }\n\n /**\n * Assert that the password is in sync with the global password.\n *\n * @param options - The options for asserting the password is in sync.\n * @param options.skipCache - Whether to skip the cache check.\n * @param options.skipLock - Whether to skip the lock acquisition. (to prevent deadlock in case the caller already acquired the lock)\n * @returns The global auth public key and the latest key index.\n * @throws If the password is outdated.\n */\n async #assertPasswordInSync(options?: {\n skipCache?: boolean;\n skipLock?: boolean;\n }): Promise<{\n authPubKey: SEC1EncodedPublicKey;\n latestKeyIndex: number;\n }> {\n this.#assertIsAuthenticatedUser(this.state);\n const {\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n } = this.state;\n\n const { authPubKey, keyIndex: latestKeyIndex } = await this.toprfClient\n .fetchAuthPubKey({\n nodeAuthTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n })\n .catch((error) => {\n log('Error fetching auth pub key', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.FailedToFetchAuthPubKey,\n {\n cause: error,\n },\n );\n });\n const isPasswordOutdated = await this.checkIsPasswordOutdated({\n ...options,\n globalAuthPubKey: authPubKey,\n });\n if (isPasswordOutdated) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.OutdatedPassword,\n );\n }\n return { authPubKey, latestKeyIndex };\n }\n\n #resetPasswordOutdatedCache(): void {\n this.update((state) => {\n delete state.passwordOutdatedCache;\n });\n }\n\n /**\n * Refresh expired nodeAuthTokens, accessToken, and metadataAccessToken using\n * the stored refresh token.\n *\n * Concurrent callers share a single in-flight HTTP request — if a refresh is\n * already in-progress the returned promise resolves when that request settles\n * rather than firing a duplicate request with the same token.\n *\n * @returns A promise that resolves when the tokens have been refreshed.\n */\n async refreshAuthTokens(): Promise<void> {\n // Coalesce concurrent calls to avoid issuing parallel HTTP requests\n // with the same refresh token.\n if (this.#pendingRefreshPromise) {\n return this.#pendingRefreshPromise;\n }\n\n const promise = this.#doRefreshAuthTokens().finally(() => {\n if (this.#pendingRefreshPromise === promise) {\n this.#pendingRefreshPromise = undefined;\n }\n });\n\n this.#pendingRefreshPromise = promise;\n\n return promise;\n }\n\n /**\n * Internal implementation of token refresh. Called exclusively by\n * `refreshAuthTokens` which gates concurrent access via\n * `#pendingRefreshPromise`.\n */\n async #doRefreshAuthTokens(): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n const { refreshToken } = this.state;\n\n const res = await this.#refreshJWTToken({\n connection: this.state.authConnection,\n refreshToken,\n }).catch((error) => {\n // Distinguish a server-side token rejection (401) from transient\n // failures so callers can apply the appropriate recovery strategy.\n const httpStatusCode = (error as Error & { statusCode?: number })\n .statusCode;\n log('Error refreshing JWT tokens', error, { httpStatusCode });\n const isTokenRevoked =\n error instanceof Error &&\n error.name === 'RefreshTokenHttpError' &&\n httpStatusCode === 401;\n throw new SeedlessOnboardingError(\n isTokenRevoked\n ? SeedlessOnboardingControllerErrorMessage.InvalidRefreshToken\n : SeedlessOnboardingControllerErrorMessage.FailedToRefreshJWTTokens,\n {\n cause: error,\n },\n );\n });\n\n try {\n const { idTokens, accessToken, metadataAccessToken } = res;\n // Re-authenticate with the refreshed id tokens to update node auth\n // tokens, accessToken, and metadataAccessToken in state.\n await this.#reAuthenticate({\n idTokens,\n accessToken,\n metadataAccessToken,\n });\n\n // update the vault with new access token if wallet is unlocked\n if (this.#isUnlocked && this.#cachedDecryptedVaultData) {\n const updatedVaultData = {\n ...this.#cachedDecryptedVaultData,\n accessToken,\n };\n const pwEncKey = this.#cachedDecryptedVaultData.toprfPwEncryptionKey;\n\n await this.#updateVault({\n vaultData: updatedVaultData,\n pwEncKey,\n });\n\n // Proactively rotate the refresh token now that we have vault access.\n await this.rotateRefreshToken().catch((error) => {\n // Rotation failure is intentionally non-fatal: the JWT refresh\n // itself succeeded and the caller should not be blocked.\n // However the user is now operating with a stale refresh token\n // that may be revoked server-side, so log prominently.\n log(\n 'Failed to rotate refresh token after successful JWT refresh. ' +\n 'The user may be logged out when the old token is revoked.',\n error,\n );\n });\n }\n } catch (error) {\n log('Error refreshing node auth tokens', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Re-authenticate the user using freshly issued tokens from a JWT refresh.\n *\n * Unlike the public `authenticate` method, this variant is called exclusively\n * from token-refresh paths where the user's identity has already been\n * established. It only accepts the tokens returned by the JWT-refresh\n * service (`idTokens`, `accessToken`, `metadataAccessToken`) and reads all\n * other auth-connection details from the existing controller state.\n *\n * `refreshToken` and `revokeToken` are intentionally absent — token-refresh\n * paths must not touch `state.refreshToken` directly; that field is managed\n * exclusively by `rotateRefreshToken`.\n *\n * @param params - Tokens issued by the JWT-refresh service.\n * @param params.idTokens - New node id tokens.\n * @param params.accessToken - New access token.\n * @param params.metadataAccessToken - New metadata access token.\n * @returns A promise that resolves to the authentication result.\n */\n async #reAuthenticate(params: {\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n }): Promise<AuthenticateResult> {\n const { idTokens, accessToken, metadataAccessToken } = params;\n const {\n authConnection,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n socialLoginEmail,\n } = this.state;\n\n try {\n const authenticationResult = await this.toprfClient.authenticate({\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n authConnectionId: authConnectionId!,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n userId: userId!,\n idTokens,\n groupedAuthConnectionId,\n });\n\n this.update((state) => {\n state.nodeAuthTokens = authenticationResult.nodeAuthTokens;\n state.authConnection = authConnection;\n state.authConnectionId = authConnectionId;\n state.groupedAuthConnectionId = groupedAuthConnectionId;\n state.userId = userId;\n state.socialLoginEmail = socialLoginEmail;\n state.metadataAccessToken = metadataAccessToken;\n state.accessToken = accessToken;\n assertIsSeedlessOnboardingUserAuthenticated(state);\n state.isSeedlessOnboardingUserAuthenticated = true;\n });\n\n return authenticationResult;\n } catch (error) {\n log('Error re-authenticating user', error);\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.AuthenticationError,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Rotate the refresh token — fetch a new refresh/revoke token pair from the\n * auth service and persist the new revoke token in the vault.\n *\n * This method should be called after a successful JWT refresh.\n *\n * @returns A Promise that resolves to void.\n */\n async rotateRefreshToken(): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const vaultData = this.#cachedDecryptedVaultData;\n // Safety net: the caller (#doRefreshAuthTokens) already guards with\n // `this.#isUnlocked && this.#cachedDecryptedVaultData`, so this branch\n // is unreachable in normal flow. This check is added to satisfy the linter and\n // to make sure any future caller of this method does not bypass the check.\n /* istanbul ignore if */\n if (!vaultData) {\n throw new SeedlessOnboardingError(\n SeedlessOnboardingControllerErrorMessage.VaultLocked,\n );\n }\n const { refreshToken } = this.state;\n const { toprfPwEncryptionKey: pwEncKey, revokeToken } = vaultData;\n const { newRevokeToken, newRefreshToken } = await this.#renewRefreshToken({\n connection: this.state.authConnection,\n revokeToken,\n });\n\n if (newRevokeToken && newRefreshToken) {\n // Persist the new revoke token to the vault first. Only update state after\n // the vault write succeeds, so state and vault stay in sync if the write fails.\n await this.#updateVault({\n vaultData: {\n ...vaultData,\n revokeToken: newRevokeToken,\n },\n pwEncKey,\n });\n\n this.update((state) => {\n state.revokeToken = newRevokeToken;\n state.refreshToken = newRefreshToken;\n });\n\n // add the old refresh token to the list to be revoked later when possible\n this.#addRefreshTokenToRevokeList({\n refreshToken,\n revokeToken,\n });\n }\n }\n\n /**\n * Revoke all pending refresh tokens.\n *\n * This method is to be called after user is authenticated.\n *\n * @returns A Promise that resolves to void.\n */\n async revokePendingRefreshTokens(): Promise<void> {\n return await this.#withControllerLock(async () => {\n this.#assertIsAuthenticatedUser(this.state);\n const { pendingToBeRevokedTokens } = this.state;\n if (!pendingToBeRevokedTokens || pendingToBeRevokedTokens.length === 0) {\n return;\n }\n\n // revoke all pending refresh tokens in parallel\n const promises = pendingToBeRevokedTokens.map(({ revokeToken }) => {\n const revokePromise = async (): Promise<string | null> => {\n try {\n await this.#revokeRefreshToken({\n connection: this.state.authConnection as AuthConnection,\n revokeToken,\n });\n return revokeToken;\n } catch (error) {\n log('Error revoking refresh token', error);\n return null;\n }\n };\n return revokePromise();\n });\n const result = await Promise.all(promises); // no need to do Promise.allSettled because the promise already handle try catch\n // filter out the null values\n const revokedTokens = result.filter((token) => token !== null);\n if (revokedTokens.length > 0) {\n // update the state to remove the revoked tokens once all concurrent token revoke finish\n this.update((state) => {\n state.pendingToBeRevokedTokens =\n state.pendingToBeRevokedTokens?.filter(\n (token) => !revokedTokens.includes(token.revokeToken),\n );\n });\n }\n });\n }\n\n /**\n * Get the access token from the state.\n *\n * If the tokens are expired, the method will refresh them and return the new access token.\n *\n * @returns The access token.\n */\n async getAccessToken(): Promise<string | undefined> {\n return this.#withControllerLock(async () => {\n this.#assertIsAuthenticatedUser(this.state);\n\n return this.#executeWithTokenRefresh(async () => {\n return this.state.accessToken;\n }, 'getAccessToken');\n });\n }\n\n /**\n * Add a pending refresh, revoke token to the state to be revoked later.\n *\n * @param params - The parameters for adding a pending refresh, revoke token.\n * @param params.refreshToken - The refresh token to add.\n * @param params.revokeToken - The revoke token to add.\n */\n #addRefreshTokenToRevokeList({\n refreshToken,\n revokeToken,\n }: {\n refreshToken: string;\n revokeToken: string;\n }): void {\n this.update((state) => {\n state.pendingToBeRevokedTokens = [\n ...(state.pendingToBeRevokedTokens ?? []),\n { refreshToken, revokeToken },\n ];\n });\n }\n\n /**\n * Executes an operation with automatic token refresh on expiration.\n *\n * This wrapper method automatically handles token expiration by refreshing tokens\n * and retrying the operation. It can be used by any method that might encounter\n * token expiration errors.\n *\n * @param operation - The operation to execute that might require valid tokens.\n * @param operationName - A descriptive name for the operation (used in error messages).\n * @returns A promise that resolves to the result of the operation.\n * @throws The original error if it's not token-related, or refresh error if token refresh fails.\n */\n async #executeWithTokenRefresh<Result>(\n operation: () => Promise<Result>,\n operationName: string,\n ): Promise<Result> {\n try {\n if (this.#checkTokensExpired()) {\n log(\n `JWT token expired during ${operationName}, attempting to refresh tokens`,\n 'node auth token exp check',\n );\n await this.refreshAuthTokens();\n }\n\n return await operation();\n } catch (error) {\n // Check if this is a token expiration error\n if (isAuthTokenError(error)) {\n log(\n `Token expired during ${operationName}, attempting to refresh tokens`,\n error,\n );\n try {\n // Refresh the tokens\n await this.refreshAuthTokens();\n // Retry the operation with fresh tokens\n return await operation();\n } catch (refreshError) {\n log(`Error refreshing tokens during ${operationName}`, refreshError);\n throw refreshError;\n }\n } else {\n // Re-throw non-token-related errors\n throw error;\n }\n }\n }\n\n /**\n * Check if the tokens are expired.\n *\n * @returns True if the tokens are expired, false otherwise.\n */\n #checkTokensExpired(): boolean {\n // proactively check for expired tokens and refresh them if needed\n const isNodeAuthTokenExpired = this.checkNodeAuthTokenExpired();\n const isMetadataAccessTokenExpired = this.checkMetadataAccessTokenExpired();\n // access token is only accessible when the vault is unlocked\n // so skip the check if the vault is locked\n let isAccessTokenExpired = false;\n if (this.#isUnlocked) {\n isAccessTokenExpired = this.checkAccessTokenExpired();\n }\n\n return (\n isNodeAuthTokenExpired ||\n isMetadataAccessTokenExpired ||\n isAccessTokenExpired\n );\n }\n\n /**\n * Check if the current node auth token is expired.\n *\n * @returns True if the current node auth token is expired, false otherwise.\n */\n public checkNodeAuthTokenExpired(): boolean {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { nodeAuthTokens } = this.state;\n // all auth tokens should be expired at the same time so we can check the first one\n const firstAuthToken = nodeAuthTokens[0]?.authToken;\n // node auth token is base64 encoded json object\n const decodedToken = decodeNodeAuthToken(firstAuthToken);\n // Node auth tokens do not carry a reliable iat field — use exact expiry.\n return isTokenNearExpiry(decodedToken.exp);\n }\n\n /**\n * Check if the current metadata access token should be refreshed.\n * Returns true when the token is expired or when less than 10% of its\n * lifetime remains (proactive refresh).\n *\n * @returns True if the metadata access token should be refreshed, false otherwise.\n */\n public checkMetadataAccessTokenExpired(): boolean {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n const { metadataAccessToken } = this.state;\n // assertIsAuthenticatedUser will throw if metadataAccessToken is missing\n const decodedToken = decodeJWTToken(metadataAccessToken as string);\n return isTokenNearExpiry(decodedToken.exp, decodedToken.iat);\n } catch {\n return true; // Consider unauthenticated user as having expired tokens\n }\n }\n\n /**\n * Check if the current access token should be refreshed.\n * Returns true when the token is expired or when less than 10% of its\n * lifetime remains (proactive refresh).\n * When the vault is locked, the access token is not accessible, so we return false.\n *\n * @returns True if the access token should be refreshed, false otherwise.\n */\n public checkAccessTokenExpired(): boolean {\n try {\n this.#assertIsAuthenticatedUser(this.state);\n const { accessToken } = this.state;\n if (!accessToken) {\n return true; // Consider missing token as expired\n }\n const decodedToken = decodeJWTToken(accessToken);\n return isTokenNearExpiry(decodedToken.exp, decodedToken.iat);\n } catch {\n return true; // Consider unauthenticated user as having expired tokens\n }\n }\n\n async #identifyIncompleteMetadataBackup(password: string): Promise<void> {\n const deserializedVaultData =\n this.#cachedDecryptedVaultData as DeserializedVaultData;\n\n await trackIncompleteMetadataBackupEvents({\n fetchAllSecretDataFn: () =>\n this.toprfClient.fetchAllSecretDataItems({\n decKey: deserializedVaultData.toprfEncryptionKey,\n authKeyPair: deserializedVaultData.toprfAuthKeyPair,\n }),\n getPrimaryKeyringSeedPhraseFn: () =>\n this.messenger.call('KeyringController:exportSeedPhrase', {\n password,\n }),\n trackEvent: (event) =>\n this.messenger.call('AnalyticsController:trackEvent', event),\n logFn: log,\n });\n }\n}\n\n/**\n * Lock the given mutex before executing the given function,\n * and release it after the function is resolved or after an\n * error is thrown.\n *\n * @param mutex - The mutex to lock.\n * @param callback - The function to execute while the mutex is locked.\n * @returns The result of the function.\n */\nasync function withLock<Result>(\n mutex: Mutex,\n callback: MutuallyExclusiveCallback<Result>,\n): Promise<Result> {\n const releaseLock = await mutex.acquire();\n\n try {\n return await callback({ releaseLock });\n } finally {\n releaseLock();\n }\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -229,8 +229,8 @@ export type VaultData = {
229
229
  accessToken: string;
230
230
  };
231
231
  export type DeserializedVaultData = Pick<VaultData, 'accessToken' | 'revokeToken'> & {
232
- toprfEncryptionKey: Uint8Array;
233
- toprfPwEncryptionKey: Uint8Array;
232
+ toprfEncryptionKey: Uint8Array<ArrayBuffer>;
233
+ toprfPwEncryptionKey: Uint8Array<ArrayBuffer>;
234
234
  toprfAuthKeyPair: KeyPair;
235
235
  };
236
236
  export type SecretDataType = Uint8Array | string | number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n EncAccountDataType,\n KeyPair,\n NodeAuthTokens,\n} from '@metamask/toprf-secure-backup';\nimport type { MutexInterface } from 'async-mutex';\n\nimport type { AuthConnection, SecretType } from './constants.js';\n\n/**\n * The backup state of the secret data.\n * Each secret data added/restored will be stored in the state locally.\n *\n * This is used to track the backup status of the secret data.\n */\nexport type SocialBackupsMetadata = {\n /**\n * The hash of the secret data.\n */\n hash: string;\n\n /**\n * The type of the secret data.\n */\n type: SecretType;\n\n /**\n * The optional keyringId to identify the keyring that the secret data belongs to.\n *\n * This is only required for `Mnemonic` secret data.\n */\n keyringId?: string;\n};\n\nexport type AuthenticatedUserDetails = {\n /**\n * Type of social login provider.\n */\n authConnection: AuthConnection;\n\n /**\n * The node auth tokens from OAuth User authentication after the Social login.\n *\n * This values are used to authenticate users when they go through the Seedless Onboarding flow.\n */\n nodeAuthTokens: NodeAuthTokens;\n\n /**\n * OAuth connection id from web3auth dashboard.\n */\n authConnectionId: string;\n\n /**\n * The optional grouped authConnectionId to authenticate the user with Web3Auth network.\n */\n groupedAuthConnectionId?: string;\n\n /**\n * The user email or ID from Social login.\n */\n userId: string;\n\n /**\n * The user email from Social login.\n */\n socialLoginEmail: string;\n\n /**\n * The refresh token used to refresh expired nodeAuthTokens.\n */\n refreshToken: string;\n};\n\nexport type SRPBackedUpUserDetails = {\n /**\n * The public key of the authentication key pair in base64 format.\n *\n * This value is used to check if the password is outdated compare to the global password and find backed up old password.\n */\n authPubKey: string;\n};\n\n/**\n * The data of the recovery error.\n */\nexport type RecoveryErrorData = {\n /**\n * The remaining time in seconds before the user can try again.\n */\n remainingTime: number;\n\n /**\n * The number of attempts made by the user.\n */\n numberOfAttempts: number;\n};\n\n/**\n * Non-sensitive type labels for each secret metadata item, in the same order\n * as fetched secret data (after sorting). Uses `dataType` when present,\n * otherwise falls back to `SecretType`.\n */\nexport type InvalidPrimarySecretDataTypeErrorData = (\n | SecretType\n | EncAccountDataType\n)[];\n\n// State\nexport type SeedlessOnboardingControllerState =\n Partial<AuthenticatedUserDetails> &\n Partial<SRPBackedUpUserDetails> & {\n /**\n * Encrypted array of serialized keyrings data.\n */\n vault?: string;\n\n /**\n * The hashes of the seed phrase backups.\n *\n * This is to facilitate the UI to display backup status of the seed phrases.\n */\n socialBackupsMetadata: SocialBackupsMetadata[];\n\n /**\n * The encryption key derived from the password and used to encrypt\n * the vault.\n */\n vaultEncryptionKey?: string;\n\n /**\n * The salt used to derive the encryption key from the password.\n */\n vaultEncryptionSalt?: string;\n\n /**\n * Cache for checkIsPasswordOutdated result and timestamp.\n */\n passwordOutdatedCache?: { isExpiredPwd: boolean; timestamp: number };\n\n /**\n * The refresh token used to refresh expired nodeAuthTokens.\n * This is persisted in state.\n */\n refreshToken?: string;\n\n /**\n * The revoke token used to revoke refresh token and get new refresh token and new revoke token.\n * This is temporarily stored in state during authentication and then persisted in the vault.\n */\n revokeToken?: string;\n\n /**\n * The refresh token and revoke token to be revoked.\n * This is persisted in state to revoke old refresh token when possible.\n */\n pendingToBeRevokedTokens?: {\n refreshToken: string;\n revokeToken: string;\n }[];\n\n /**\n * The encrypted seedless encryption key used to encrypt the seedless vault.\n */\n encryptedSeedlessEncryptionKey?: string;\n\n /**\n * The encrypted keyring encryption key used to encrypt the keyring vault.\n */\n encryptedKeyringEncryptionKey?: string;\n\n /**\n * The access token used for pairing with profile sync auth service and to access other services.\n */\n accessToken?: string;\n\n /**\n * The metadata access token used to access the metadata service.\n *\n * This token is used to access the metadata service before the vault is created or unlocked.\n */\n metadataAccessToken?: string;\n\n /**\n * Whether the user is authenticated with social login and TOPRF service.\n */\n isSeedlessOnboardingUserAuthenticated: boolean;\n\n /**\n * Tracks which seedless onboarding migrations have been applied.\n * Used to prevent re-running migrations.\n */\n migrationVersion: number;\n };\n\n/**\n * Additional key deriver for the TOPRF client.\n *\n * This is a function that takes a seed and salt and returns a key in bytes (Uint8Array).\n * It is used as an additional step during key derivation. This can be used, for example, to inject a slow key\n * derivation step to protect against local brute force attacks on the password.\n *\n * @default browser-passworder @link https://github.com/MetaMask/browser-passworder\n */\nexport type ToprfKeyDeriver = {\n /**\n * Derive a key from a seed and salt.\n *\n * @param seed - The seed to derive the key from.\n * @param salt - The salt to derive the key from.\n * @returns The derived key.\n */\n deriveKey: (seed: Uint8Array, salt: Uint8Array) => Promise<Uint8Array>;\n};\n\nexport type RefreshJWTToken = (params: {\n connection: AuthConnection;\n refreshToken: string;\n}) => Promise<{\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n}>;\n\nexport type RevokeRefreshToken = (params: {\n connection: AuthConnection;\n revokeToken: string;\n}) => Promise<void>;\n\nexport type RenewRefreshToken = (params: {\n connection: AuthConnection;\n revokeToken: string;\n}) => Promise<{\n newRevokeToken: string;\n newRefreshToken: string;\n}>;\n\n/**\n * A function executed within a mutually exclusive lock, with\n * a mutex releaser in its option bag.\n *\n * @param releaseLock - A function to release the lock.\n */\nexport type MutuallyExclusiveCallback<Result> = ({\n releaseLock,\n}: {\n releaseLock: MutexInterface.Releaser;\n}) => Promise<Result>;\n\n/**\n * The structure of the data which is serialized and stored in the vault.\n */\nexport type VaultData = {\n /**\n * The encryption key to encrypt the seed phrase.\n */\n toprfEncryptionKey: string;\n /**\n * The encryption key to encrypt the password.\n */\n toprfPwEncryptionKey: string;\n /**\n * The authentication key pair to authenticate the TOPRF.\n */\n toprfAuthKeyPair: string;\n /**\n * The revoke token to revoke refresh token and get new refresh token and new revoke token.\n * The revoke token may no longer be available after a large number of password changes. In this case, re-authentication is advised.\n */\n revokeToken: string;\n /**\n * The access token used for pairing with profile sync auth service and to access other services.\n */\n accessToken: string;\n};\n\nexport type DeserializedVaultData = Pick<\n VaultData,\n 'accessToken' | 'revokeToken'\n> & {\n toprfEncryptionKey: Uint8Array;\n toprfPwEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n};\n\nexport type SecretDataType = Uint8Array | string | number;\n\nexport type DecodedNodeAuthToken = {\n /**\n * The expiration time of the token in seconds.\n */\n exp: number;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n temp_key_x: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n temp_key_y: string;\n aud: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n verifier_name: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n verifier_id: string;\n scope: string;\n signature: string;\n};\n\nexport type DecodedBaseJWTToken = {\n /**\n * The expiration time of the token in seconds.\n */\n exp: number;\n /**\n * The issued at time of the token in seconds.\n */\n iat: number;\n /**\n * The audience of the token.\n */\n aud: string;\n /**\n * The issuer of the token.\n */\n iss: string;\n /**\n * The subject of the token.\n */\n sub: string;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n EncAccountDataType,\n KeyPair,\n NodeAuthTokens,\n} from '@metamask/toprf-secure-backup';\nimport type { MutexInterface } from 'async-mutex';\n\nimport type { AuthConnection, SecretType } from './constants.js';\n\n/**\n * The backup state of the secret data.\n * Each secret data added/restored will be stored in the state locally.\n *\n * This is used to track the backup status of the secret data.\n */\nexport type SocialBackupsMetadata = {\n /**\n * The hash of the secret data.\n */\n hash: string;\n\n /**\n * The type of the secret data.\n */\n type: SecretType;\n\n /**\n * The optional keyringId to identify the keyring that the secret data belongs to.\n *\n * This is only required for `Mnemonic` secret data.\n */\n keyringId?: string;\n};\n\nexport type AuthenticatedUserDetails = {\n /**\n * Type of social login provider.\n */\n authConnection: AuthConnection;\n\n /**\n * The node auth tokens from OAuth User authentication after the Social login.\n *\n * This values are used to authenticate users when they go through the Seedless Onboarding flow.\n */\n nodeAuthTokens: NodeAuthTokens;\n\n /**\n * OAuth connection id from web3auth dashboard.\n */\n authConnectionId: string;\n\n /**\n * The optional grouped authConnectionId to authenticate the user with Web3Auth network.\n */\n groupedAuthConnectionId?: string;\n\n /**\n * The user email or ID from Social login.\n */\n userId: string;\n\n /**\n * The user email from Social login.\n */\n socialLoginEmail: string;\n\n /**\n * The refresh token used to refresh expired nodeAuthTokens.\n */\n refreshToken: string;\n};\n\nexport type SRPBackedUpUserDetails = {\n /**\n * The public key of the authentication key pair in base64 format.\n *\n * This value is used to check if the password is outdated compare to the global password and find backed up old password.\n */\n authPubKey: string;\n};\n\n/**\n * The data of the recovery error.\n */\nexport type RecoveryErrorData = {\n /**\n * The remaining time in seconds before the user can try again.\n */\n remainingTime: number;\n\n /**\n * The number of attempts made by the user.\n */\n numberOfAttempts: number;\n};\n\n/**\n * Non-sensitive type labels for each secret metadata item, in the same order\n * as fetched secret data (after sorting). Uses `dataType` when present,\n * otherwise falls back to `SecretType`.\n */\nexport type InvalidPrimarySecretDataTypeErrorData = (\n | SecretType\n | EncAccountDataType\n)[];\n\n// State\nexport type SeedlessOnboardingControllerState =\n Partial<AuthenticatedUserDetails> &\n Partial<SRPBackedUpUserDetails> & {\n /**\n * Encrypted array of serialized keyrings data.\n */\n vault?: string;\n\n /**\n * The hashes of the seed phrase backups.\n *\n * This is to facilitate the UI to display backup status of the seed phrases.\n */\n socialBackupsMetadata: SocialBackupsMetadata[];\n\n /**\n * The encryption key derived from the password and used to encrypt\n * the vault.\n */\n vaultEncryptionKey?: string;\n\n /**\n * The salt used to derive the encryption key from the password.\n */\n vaultEncryptionSalt?: string;\n\n /**\n * Cache for checkIsPasswordOutdated result and timestamp.\n */\n passwordOutdatedCache?: { isExpiredPwd: boolean; timestamp: number };\n\n /**\n * The refresh token used to refresh expired nodeAuthTokens.\n * This is persisted in state.\n */\n refreshToken?: string;\n\n /**\n * The revoke token used to revoke refresh token and get new refresh token and new revoke token.\n * This is temporarily stored in state during authentication and then persisted in the vault.\n */\n revokeToken?: string;\n\n /**\n * The refresh token and revoke token to be revoked.\n * This is persisted in state to revoke old refresh token when possible.\n */\n pendingToBeRevokedTokens?: {\n refreshToken: string;\n revokeToken: string;\n }[];\n\n /**\n * The encrypted seedless encryption key used to encrypt the seedless vault.\n */\n encryptedSeedlessEncryptionKey?: string;\n\n /**\n * The encrypted keyring encryption key used to encrypt the keyring vault.\n */\n encryptedKeyringEncryptionKey?: string;\n\n /**\n * The access token used for pairing with profile sync auth service and to access other services.\n */\n accessToken?: string;\n\n /**\n * The metadata access token used to access the metadata service.\n *\n * This token is used to access the metadata service before the vault is created or unlocked.\n */\n metadataAccessToken?: string;\n\n /**\n * Whether the user is authenticated with social login and TOPRF service.\n */\n isSeedlessOnboardingUserAuthenticated: boolean;\n\n /**\n * Tracks which seedless onboarding migrations have been applied.\n * Used to prevent re-running migrations.\n */\n migrationVersion: number;\n };\n\n/**\n * Additional key deriver for the TOPRF client.\n *\n * This is a function that takes a seed and salt and returns a key in bytes (Uint8Array).\n * It is used as an additional step during key derivation. This can be used, for example, to inject a slow key\n * derivation step to protect against local brute force attacks on the password.\n *\n * @default browser-passworder @link https://github.com/MetaMask/browser-passworder\n */\nexport type ToprfKeyDeriver = {\n /**\n * Derive a key from a seed and salt.\n *\n * @param seed - The seed to derive the key from.\n * @param salt - The salt to derive the key from.\n * @returns The derived key.\n */\n deriveKey: (seed: Uint8Array, salt: Uint8Array) => Promise<Uint8Array>;\n};\n\nexport type RefreshJWTToken = (params: {\n connection: AuthConnection;\n refreshToken: string;\n}) => Promise<{\n idTokens: string[];\n accessToken: string;\n metadataAccessToken: string;\n}>;\n\nexport type RevokeRefreshToken = (params: {\n connection: AuthConnection;\n revokeToken: string;\n}) => Promise<void>;\n\nexport type RenewRefreshToken = (params: {\n connection: AuthConnection;\n revokeToken: string;\n}) => Promise<{\n newRevokeToken: string;\n newRefreshToken: string;\n}>;\n\n/**\n * A function executed within a mutually exclusive lock, with\n * a mutex releaser in its option bag.\n *\n * @param releaseLock - A function to release the lock.\n */\nexport type MutuallyExclusiveCallback<Result> = ({\n releaseLock,\n}: {\n releaseLock: MutexInterface.Releaser;\n}) => Promise<Result>;\n\n/**\n * The structure of the data which is serialized and stored in the vault.\n */\nexport type VaultData = {\n /**\n * The encryption key to encrypt the seed phrase.\n */\n toprfEncryptionKey: string;\n /**\n * The encryption key to encrypt the password.\n */\n toprfPwEncryptionKey: string;\n /**\n * The authentication key pair to authenticate the TOPRF.\n */\n toprfAuthKeyPair: string;\n /**\n * The revoke token to revoke refresh token and get new refresh token and new revoke token.\n * The revoke token may no longer be available after a large number of password changes. In this case, re-authentication is advised.\n */\n revokeToken: string;\n /**\n * The access token used for pairing with profile sync auth service and to access other services.\n */\n accessToken: string;\n};\n\nexport type DeserializedVaultData = Pick<\n VaultData,\n 'accessToken' | 'revokeToken'\n> & {\n toprfEncryptionKey: Uint8Array<ArrayBuffer>;\n toprfPwEncryptionKey: Uint8Array<ArrayBuffer>;\n toprfAuthKeyPair: KeyPair;\n};\n\nexport type SecretDataType = Uint8Array | string | number;\n\nexport type DecodedNodeAuthToken = {\n /**\n * The expiration time of the token in seconds.\n */\n exp: number;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n temp_key_x: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n temp_key_y: string;\n aud: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n verifier_name: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention -- to match with the actual token\n verifier_id: string;\n scope: string;\n signature: string;\n};\n\nexport type DecodedBaseJWTToken = {\n /**\n * The expiration time of the token in seconds.\n */\n exp: number;\n /**\n * The issued at time of the token in seconds.\n */\n iat: number;\n /**\n * The audience of the token.\n */\n aud: string;\n /**\n * The issuer of the token.\n */\n iss: string;\n /**\n * The subject of the token.\n */\n sub: string;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAGnB,MAAM,+BAA+B,CAAC;AASvC,OAAO,EAEL,UAAU,EACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,qCAAqC,EACrC,SAAS,EACV,MAAM,aAAa,CAAC;AAGrB;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAcjE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAYtE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,qBAAqB,CAW5E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAevD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAOlE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAS7D;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAsBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,EACZ,GAAG,SAAoB,GACtB,OAAO,CAYT;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASxD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,CAUZ;AAED;;;;;GAKG;AACH,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GAC7C,qCAAqC,CAEvC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EACL,kBAAkB,EAGnB,MAAM,+BAA+B,CAAC;AASvC,OAAO,EAEL,UAAU,EACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,qCAAqC,EACrC,SAAS,EACV,MAAM,aAAa,CAAC;AAGrB;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAIvE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAcjE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAYtE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,qBAAqB,CAW5E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAevD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAOlE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAS7D;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAsBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,EACZ,GAAG,SAAoB,GACtB,OAAO,CAYT;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASxD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,CAUZ;AAED;;;;;GAKG;AACH,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GAC7C,qCAAqC,CAEvC"}
@@ -1,6 +1,5 @@
1
1
  import { EncAccountDataType, TOPRFError, TOPRFErrorCode, } from '@metamask/toprf-secure-backup';
2
- import { base64ToBytes, bigIntToHex, bytesToBase64, hexToBigInt, } from '@metamask/utils';
3
- import { bytesToUtf8 } from '@noble/ciphers/utils';
2
+ import { base64ToBytes, bigIntToHex, bytesToBase64, bytesToString, hexToBigInt, } from '@metamask/utils';
4
3
  import { SeedlessOnboardingControllerErrorMessage, SecretType, } from '../constants.js';
5
4
  import { assertIsValidVaultData } from './assertions.js';
6
5
  /**
@@ -10,7 +9,7 @@ import { assertIsValidVaultData } from './assertions.js';
10
9
  * @returns The decoded node auth token.
11
10
  */
12
11
  export function decodeNodeAuthToken(token) {
13
- return JSON.parse(bytesToUtf8(base64ToBytes(token)));
12
+ return JSON.parse(bytesToString(base64ToBytes(token)));
14
13
  }
15
14
  /**
16
15
  * Decode JWT token
@@ -28,7 +27,7 @@ export function decodeJWTToken(token) {
28
27
  const payload = parts[1];
29
28
  // Add padding if needed for base64 decoding
30
29
  const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
31
- return JSON.parse(bytesToUtf8(base64ToBytes(paddedPayload)));
30
+ return JSON.parse(bytesToString(base64ToBytes(paddedPayload)));
32
31
  }
33
32
  /**
34
33
  * Serialize the vault data.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeyPair } from '@metamask/toprf-secure-backup';\nimport {\n EncAccountDataType,\n TOPRFError,\n TOPRFErrorCode,\n} from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bigIntToHex,\n bytesToBase64,\n hexToBigInt,\n} from '@metamask/utils';\nimport { bytesToUtf8 } from '@noble/ciphers/utils';\n\nimport {\n SeedlessOnboardingControllerErrorMessage,\n SecretType,\n} from '../constants.js';\nimport type { SecretMetadata } from '../SecretMetadata.js';\nimport type {\n DecodedBaseJWTToken,\n DecodedNodeAuthToken,\n DeserializedVaultData,\n InvalidPrimarySecretDataTypeErrorData,\n VaultData,\n} from '../types.js';\nimport { assertIsValidVaultData } from './assertions.js';\n\n/**\n * Decode the node auth token from base64 to json object.\n *\n * @param token - The node auth token to decode.\n * @returns The decoded node auth token.\n */\nexport function decodeNodeAuthToken(token: string): DecodedNodeAuthToken {\n return JSON.parse(bytesToUtf8(base64ToBytes(token))) as DecodedNodeAuthToken;\n}\n\n/**\n * Decode JWT token\n *\n * @param token - The JWT token to decode.\n * @returns The decoded JWT token.\n */\nexport function decodeJWTToken(token: string): DecodedBaseJWTToken {\n // JWT tokens have 3 parts separated by dots: header.payload.signature\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT token format');\n }\n\n // Decode the payload (second part)\n const payload = parts[1];\n // Add padding if needed for base64 decoding\n const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);\n return JSON.parse(\n bytesToUtf8(base64ToBytes(paddedPayload)),\n ) as DecodedBaseJWTToken;\n}\n\n/**\n * Serialize the vault data.\n *\n * @param data - The vault data to serialize.\n * @returns The serialized vault data.\n */\nexport function serializeVaultData(data: DeserializedVaultData): string {\n const toprfEncryptionKey = bytesToBase64(data.toprfEncryptionKey);\n const toprfPwEncryptionKey = bytesToBase64(data.toprfPwEncryptionKey);\n const toprfAuthKeyPair = serializeToprfAuthKeyPair(data.toprfAuthKeyPair);\n\n return JSON.stringify({\n toprfEncryptionKey,\n toprfPwEncryptionKey,\n toprfAuthKeyPair,\n revokeToken: data.revokeToken,\n accessToken: data.accessToken,\n });\n}\n\n/**\n * Deserialize the vault data.\n *\n * @param value - The stringified vault data.\n * @returns The deserialized vault data.\n */\nexport function deserializeVaultData(value: VaultData): DeserializedVaultData {\n const toprfEncryptionKey = base64ToBytes(value.toprfEncryptionKey);\n const toprfPwEncryptionKey = base64ToBytes(value.toprfPwEncryptionKey);\n const toprfAuthKeyPair = deserializeAuthKeyPair(value.toprfAuthKeyPair);\n\n return {\n ...value,\n toprfEncryptionKey,\n toprfPwEncryptionKey,\n toprfAuthKeyPair,\n };\n}\n\n/**\n * Parse and validate decrypted vault data.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed vault data.\n * @throws If the decrypted data is not valid JSON or is not valid vault data.\n */\nexport function parseVaultData(data: unknown): VaultData {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultDataError);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultDataError);\n }\n\n assertIsValidVaultData(parsedVaultData);\n\n return parsedVaultData;\n}\n\n/**\n * Serialize TOPRF authentication key pair.\n *\n * @param keyPair - The authentication key pair to serialize.\n * @returns The serialized authentication key pair.\n */\nexport function serializeToprfAuthKeyPair(keyPair: KeyPair): string {\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(keyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(keyPair.pk),\n });\n\n return b64EncodedAuthKeyPair;\n}\n\n/**\n * Deserialize the authentication key pair.\n *\n * @param value - The stringified authentication key pair.\n * @returns The deserialized authentication key pair.\n */\nexport function deserializeAuthKeyPair(value: string): KeyPair {\n const parsedKeyPair = JSON.parse(value) as {\n sk: string;\n pk: string;\n };\n return {\n sk: hexToBigInt(parsedKeyPair.sk),\n pk: base64ToBytes(parsedKeyPair.pk),\n };\n}\n\n/**\n * Compare two JWT tokens and return the latest token.\n *\n * @param jwtToken1 - The first JWT token to compare.\n * @param jwtToken2 - The second JWT token to compare.\n * @returns The latest JWT token.\n */\nexport function compareAndGetLatestToken(\n jwtToken1: string,\n jwtToken2: string,\n): string {\n let decodedToken1: DecodedBaseJWTToken;\n let decodedToken2: DecodedBaseJWTToken;\n\n try {\n decodedToken1 = decodeJWTToken(jwtToken1);\n } catch {\n // if the first token is invalid, return the second token\n return jwtToken2;\n }\n\n try {\n decodedToken2 = decodeJWTToken(jwtToken2);\n } catch {\n // if the second token is invalid, return the first token\n return jwtToken1;\n }\n\n if (decodedToken1.exp > decodedToken2.exp) {\n return jwtToken1;\n }\n return jwtToken2;\n}\n\n/**\n * Determine whether a token should be proactively refreshed.\n *\n * When `iat` is provided: returns `true` when less than 10% of the token's\n * lifetime remains (i.e. we are in the last 10% before expiry).\n * When `iat` is omitted: returns `true` when the token is already expired.\n *\n * @param exp - Expiration time in seconds.\n * @param iat - Optional issued-at time in seconds.\n * @param now - Current time in seconds. Defaults to the current time.\n * @returns Whether the token should be refreshed.\n */\nexport function isTokenNearExpiry(\n exp: number,\n iat?: number,\n now = Date.now() / 1000,\n): boolean {\n if (iat === undefined) {\n return now >= exp;\n }\n const lifetime = exp - iat;\n // Guard against malformed tokens where iat >= exp (zero or negative lifetime).\n // Fall back to exact-expiry check so bad tokens are always considered stale.\n if (lifetime <= 0) {\n return now >= exp;\n }\n const remaining = exp - now;\n return remaining <= 0.1 * lifetime;\n}\n\n/**\n * Check whether an error indicates that a TOPRF auth token is invalid or\n * expired.\n *\n * @param error - The error to check.\n * @returns Whether the error is an auth token error.\n */\nexport function isAuthTokenError(error: unknown): boolean {\n if (error instanceof TOPRFError) {\n return (\n error.code === TOPRFErrorCode.AuthTokenExpired ||\n error.code === TOPRFErrorCode.InvalidAuthToken\n );\n }\n\n return false;\n}\n\n/**\n * Check whether an error indicates that the TOPRF key chain limit was reached.\n *\n * @param error - The error to check.\n * @returns Whether the error is a max key chain length error.\n */\nexport function isMaxKeyChainLengthError(error: unknown): boolean {\n if (error instanceof TOPRFError) {\n return error.code === TOPRFErrorCode.MaxKeyChainLengthExceeded;\n }\n\n return false;\n}\n\n/**\n * Derive SecretType from EncAccountDataType.\n *\n * This function maps the server-side data type classification to the\n * client-side secret type. This allows us to maintain a single source\n * of truth (EncAccountDataType) while still writing the SecretType to\n * the encrypted payload for backward compatibility with older clients.\n *\n * @param dataType - The EncAccountDataType to derive SecretType from.\n * @returns The corresponding SecretType.\n */\nexport function getSecretTypeFromDataType(\n dataType: EncAccountDataType,\n): SecretType {\n switch (dataType) {\n case EncAccountDataType.PrimarySrp:\n case EncAccountDataType.ImportedSrp:\n return SecretType.Mnemonic;\n case EncAccountDataType.ImportedPrivateKey:\n return SecretType.PrivateKey;\n default:\n throw new Error(`Unknown EncAccountDataType: ${String(dataType)}`);\n }\n}\n\n/**\n * Build non-sensitive type labels for secret metadata items.\n *\n * @param secrets - The SecretMetadata items in fetch order.\n * @returns One SecretType or EncAccountDataType per item.\n */\nexport function getInvalidPrimarySecretDataTypeErrorData(\n secrets: SecretMetadata<string | Uint8Array>[],\n): InvalidPrimarySecretDataTypeErrorData {\n return secrets.map((secret) => secret.dataType ?? secret.type);\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeyPair } from '@metamask/toprf-secure-backup';\nimport {\n EncAccountDataType,\n TOPRFError,\n TOPRFErrorCode,\n} from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bigIntToHex,\n bytesToBase64,\n bytesToString,\n hexToBigInt,\n} from '@metamask/utils';\n\nimport {\n SeedlessOnboardingControllerErrorMessage,\n SecretType,\n} from '../constants.js';\nimport type { SecretMetadata } from '../SecretMetadata.js';\nimport type {\n DecodedBaseJWTToken,\n DecodedNodeAuthToken,\n DeserializedVaultData,\n InvalidPrimarySecretDataTypeErrorData,\n VaultData,\n} from '../types.js';\nimport { assertIsValidVaultData } from './assertions.js';\n\n/**\n * Decode the node auth token from base64 to json object.\n *\n * @param token - The node auth token to decode.\n * @returns The decoded node auth token.\n */\nexport function decodeNodeAuthToken(token: string): DecodedNodeAuthToken {\n return JSON.parse(\n bytesToString(base64ToBytes(token)),\n ) as DecodedNodeAuthToken;\n}\n\n/**\n * Decode JWT token\n *\n * @param token - The JWT token to decode.\n * @returns The decoded JWT token.\n */\nexport function decodeJWTToken(token: string): DecodedBaseJWTToken {\n // JWT tokens have 3 parts separated by dots: header.payload.signature\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT token format');\n }\n\n // Decode the payload (second part)\n const payload = parts[1];\n // Add padding if needed for base64 decoding\n const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);\n return JSON.parse(\n bytesToString(base64ToBytes(paddedPayload)),\n ) as DecodedBaseJWTToken;\n}\n\n/**\n * Serialize the vault data.\n *\n * @param data - The vault data to serialize.\n * @returns The serialized vault data.\n */\nexport function serializeVaultData(data: DeserializedVaultData): string {\n const toprfEncryptionKey = bytesToBase64(data.toprfEncryptionKey);\n const toprfPwEncryptionKey = bytesToBase64(data.toprfPwEncryptionKey);\n const toprfAuthKeyPair = serializeToprfAuthKeyPair(data.toprfAuthKeyPair);\n\n return JSON.stringify({\n toprfEncryptionKey,\n toprfPwEncryptionKey,\n toprfAuthKeyPair,\n revokeToken: data.revokeToken,\n accessToken: data.accessToken,\n });\n}\n\n/**\n * Deserialize the vault data.\n *\n * @param value - The stringified vault data.\n * @returns The deserialized vault data.\n */\nexport function deserializeVaultData(value: VaultData): DeserializedVaultData {\n const toprfEncryptionKey = base64ToBytes(value.toprfEncryptionKey);\n const toprfPwEncryptionKey = base64ToBytes(value.toprfPwEncryptionKey);\n const toprfAuthKeyPair = deserializeAuthKeyPair(value.toprfAuthKeyPair);\n\n return {\n ...value,\n toprfEncryptionKey,\n toprfPwEncryptionKey,\n toprfAuthKeyPair,\n };\n}\n\n/**\n * Parse and validate decrypted vault data.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed vault data.\n * @throws If the decrypted data is not valid JSON or is not valid vault data.\n */\nexport function parseVaultData(data: unknown): VaultData {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultDataError);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerErrorMessage.VaultDataError);\n }\n\n assertIsValidVaultData(parsedVaultData);\n\n return parsedVaultData;\n}\n\n/**\n * Serialize TOPRF authentication key pair.\n *\n * @param keyPair - The authentication key pair to serialize.\n * @returns The serialized authentication key pair.\n */\nexport function serializeToprfAuthKeyPair(keyPair: KeyPair): string {\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(keyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(keyPair.pk),\n });\n\n return b64EncodedAuthKeyPair;\n}\n\n/**\n * Deserialize the authentication key pair.\n *\n * @param value - The stringified authentication key pair.\n * @returns The deserialized authentication key pair.\n */\nexport function deserializeAuthKeyPair(value: string): KeyPair {\n const parsedKeyPair = JSON.parse(value) as {\n sk: string;\n pk: string;\n };\n return {\n sk: hexToBigInt(parsedKeyPair.sk),\n pk: base64ToBytes(parsedKeyPair.pk),\n };\n}\n\n/**\n * Compare two JWT tokens and return the latest token.\n *\n * @param jwtToken1 - The first JWT token to compare.\n * @param jwtToken2 - The second JWT token to compare.\n * @returns The latest JWT token.\n */\nexport function compareAndGetLatestToken(\n jwtToken1: string,\n jwtToken2: string,\n): string {\n let decodedToken1: DecodedBaseJWTToken;\n let decodedToken2: DecodedBaseJWTToken;\n\n try {\n decodedToken1 = decodeJWTToken(jwtToken1);\n } catch {\n // if the first token is invalid, return the second token\n return jwtToken2;\n }\n\n try {\n decodedToken2 = decodeJWTToken(jwtToken2);\n } catch {\n // if the second token is invalid, return the first token\n return jwtToken1;\n }\n\n if (decodedToken1.exp > decodedToken2.exp) {\n return jwtToken1;\n }\n return jwtToken2;\n}\n\n/**\n * Determine whether a token should be proactively refreshed.\n *\n * When `iat` is provided: returns `true` when less than 10% of the token's\n * lifetime remains (i.e. we are in the last 10% before expiry).\n * When `iat` is omitted: returns `true` when the token is already expired.\n *\n * @param exp - Expiration time in seconds.\n * @param iat - Optional issued-at time in seconds.\n * @param now - Current time in seconds. Defaults to the current time.\n * @returns Whether the token should be refreshed.\n */\nexport function isTokenNearExpiry(\n exp: number,\n iat?: number,\n now = Date.now() / 1000,\n): boolean {\n if (iat === undefined) {\n return now >= exp;\n }\n const lifetime = exp - iat;\n // Guard against malformed tokens where iat >= exp (zero or negative lifetime).\n // Fall back to exact-expiry check so bad tokens are always considered stale.\n if (lifetime <= 0) {\n return now >= exp;\n }\n const remaining = exp - now;\n return remaining <= 0.1 * lifetime;\n}\n\n/**\n * Check whether an error indicates that a TOPRF auth token is invalid or\n * expired.\n *\n * @param error - The error to check.\n * @returns Whether the error is an auth token error.\n */\nexport function isAuthTokenError(error: unknown): boolean {\n if (error instanceof TOPRFError) {\n return (\n error.code === TOPRFErrorCode.AuthTokenExpired ||\n error.code === TOPRFErrorCode.InvalidAuthToken\n );\n }\n\n return false;\n}\n\n/**\n * Check whether an error indicates that the TOPRF key chain limit was reached.\n *\n * @param error - The error to check.\n * @returns Whether the error is a max key chain length error.\n */\nexport function isMaxKeyChainLengthError(error: unknown): boolean {\n if (error instanceof TOPRFError) {\n return error.code === TOPRFErrorCode.MaxKeyChainLengthExceeded;\n }\n\n return false;\n}\n\n/**\n * Derive SecretType from EncAccountDataType.\n *\n * This function maps the server-side data type classification to the\n * client-side secret type. This allows us to maintain a single source\n * of truth (EncAccountDataType) while still writing the SecretType to\n * the encrypted payload for backward compatibility with older clients.\n *\n * @param dataType - The EncAccountDataType to derive SecretType from.\n * @returns The corresponding SecretType.\n */\nexport function getSecretTypeFromDataType(\n dataType: EncAccountDataType,\n): SecretType {\n switch (dataType) {\n case EncAccountDataType.PrimarySrp:\n case EncAccountDataType.ImportedSrp:\n return SecretType.Mnemonic;\n case EncAccountDataType.ImportedPrivateKey:\n return SecretType.PrivateKey;\n default:\n throw new Error(`Unknown EncAccountDataType: ${String(dataType)}`);\n }\n}\n\n/**\n * Build non-sensitive type labels for secret metadata items.\n *\n * @param secrets - The SecretMetadata items in fetch order.\n * @returns One SecretType or EncAccountDataType per item.\n */\nexport function getInvalidPrimarySecretDataTypeErrorData(\n secrets: SecretMetadata<string | Uint8Array>[],\n): InvalidPrimarySecretDataTypeErrorData {\n return secrets.map((secret) => secret.dataType ?? secret.type);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/seedless-onboarding-controller",
3
- "version": "12.0.0-preview-44b7ded21",
3
+ "version": "12.0.0-preview-2750df1dc",
4
4
  "description": "Backup and rehydrate SRP(s) using social login and password",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -58,11 +58,11 @@
58
58
  "@metamask/auth-network-utils": "^0.3.0",
59
59
  "@metamask/base-controller": "^10.0.0",
60
60
  "@metamask/browser-passworder": "^6.0.0",
61
+ "@metamask/cryptography": "^1.1.2",
61
62
  "@metamask/keyring-controller": "^28.1.0",
62
63
  "@metamask/messenger": "^3.0.0",
63
64
  "@metamask/toprf-secure-backup": "^1.1.0",
64
65
  "@metamask/utils": "^12.0.0",
65
- "@noble/ciphers": "^1.3.0",
66
66
  "@noble/curves": "^1.9.7",
67
67
  "@noble/hashes": "^1.8.0",
68
68
  "async-mutex": "^0.5.0"
@@ -71,6 +71,7 @@
71
71
  "@lavamoat/allow-scripts": "^5.1.0",
72
72
  "@lavamoat/preinstall-always-fail": "^3.0.0",
73
73
  "@metamask/auto-changelog": "^6.2.1",
74
+ "@noble/ciphers": "^1.3.0",
74
75
  "@types/elliptic": "^6",
75
76
  "@types/jest": "^30.0.0",
76
77
  "@types/json-stable-stringify-without-jsonify": "^1.0.2",