@metamask-previews/seedless-onboarding-controller 0.0.0-preview-7aa27646 → 0.0.0-preview-971e1a64

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.
@@ -126,12 +126,12 @@ class SeedlessOnboardingController extends base_controller_1.BaseController {
126
126
  return (0, utils_1.remove0x)((0, auth_network_utils_1.keccak256AndHexify)((0, utils_1.stringToBytes)(idToken)));
127
127
  });
128
128
  const authenticationResult = await this.toprfClient.authenticate({
129
- verifier: groupedAuthConnectionId || authConnectionId,
130
- verifierId: userId,
129
+ authConnectionId: groupedAuthConnectionId || authConnectionId,
130
+ userId,
131
131
  idTokens: hashedIdTokenHexes,
132
- singleIdVerifierParams: {
133
- subVerifier: authConnectionId,
134
- subVerifierIdTokens: idTokens,
132
+ groupedAuthConnectionParams: {
133
+ authConnectionId,
134
+ idTokens,
135
135
  },
136
136
  });
137
137
  // update the state with the authenticated user info
@@ -279,12 +279,12 @@ _SeedlessOnboardingController_vaultEncryptor = new WeakMap(), _SeedlessOnboardin
279
279
  */
280
280
  async function _SeedlessOnboardingController_persistOprfKey(oprfKey, authPubKey) {
281
281
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
282
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
282
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
283
283
  try {
284
284
  await this.toprfClient.persistLocalKey({
285
285
  nodeAuthTokens: this.state.nodeAuthTokens,
286
- verifier,
287
- verifierId: this.state.userId,
286
+ authConnectionId,
287
+ userId: this.state.userId,
288
288
  oprfKey,
289
289
  authPubKey,
290
290
  });
@@ -303,13 +303,13 @@ async function _SeedlessOnboardingController_persistOprfKey(oprfKey, authPubKey)
303
303
  */
304
304
  async function _SeedlessOnboardingController_recoverEncKey(password) {
305
305
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
306
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
306
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
307
307
  try {
308
308
  const recoverEncKeyResult = await this.toprfClient.recoverEncKey({
309
309
  nodeAuthTokens: this.state.nodeAuthTokens,
310
310
  password,
311
- verifier,
312
- verifierId: this.state.userId,
311
+ authConnectionId,
312
+ userId: this.state.userId,
313
313
  });
314
314
  return recoverEncKeyResult;
315
315
  }
@@ -326,15 +326,16 @@ async function _SeedlessOnboardingController_recoverEncKey(password) {
326
326
  */
327
327
  async function _SeedlessOnboardingController_changeEncryptionKey(newPassword, oldPassword) {
328
328
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
329
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
329
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
330
330
  const { encKey, authKeyPair, keyShareIndex: newKeyShareIndex, } = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_recoverEncKey).call(this, oldPassword);
331
331
  return await this.toprfClient.changeEncKey({
332
332
  nodeAuthTokens: this.state.nodeAuthTokens,
333
- verifier,
334
- verifierId: this.state.userId,
333
+ authConnectionId,
334
+ userId: this.state.userId,
335
335
  oldEncKey: encKey,
336
336
  oldAuthKeyPair: authKeyPair,
337
337
  newKeyShareIndex,
338
+ oldPassword,
338
339
  newPassword,
339
340
  });
340
341
  }, _SeedlessOnboardingController_encryptAndStoreSeedPhraseBackup =
@@ -1 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.cjs","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { encrypt, decrypt } from '@metamask/browser-passworder';\nimport type {\n KeyPair,\n NodeAuthTokens,\n SEC1EncodedPublicKey,\n} from '@metamask/toprf-secure-backup';\nimport { ToprfSecureBackup } from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n remove0x,\n bigIntToHex,\n} from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n type AuthConnection,\n controllerName,\n SeedlessOnboardingControllerError,\n Web3AuthNetwork,\n} from './constants';\nimport { RecoveryError } from './errors';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { SeedPhraseMetadata } from './SeedPhraseMetadata';\nimport type {\n VaultEncryptor,\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerState,\n VaultData,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\n/**\n * Get the default state for the Seedless Onboarding Controller.\n *\n * @returns The default state for the Seedless Onboarding Controller.\n */\nexport function getDefaultSeedlessOnboardingControllerState(): SeedlessOnboardingControllerState {\n return {\n socialBackupsMetadata: [],\n };\n}\n\n/**\n * Seedless Onboarding Controller State Metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst seedlessOnboardingMetadata: StateMetadata<SeedlessOnboardingControllerState> =\n {\n vault: {\n persist: true,\n anonymous: false,\n },\n socialBackupsMetadata: {\n persist: true,\n anonymous: true,\n },\n nodeAuthTokens: {\n persist: false,\n anonymous: true,\n },\n authConnection: {\n persist: true,\n anonymous: true,\n },\n authConnectionId: {\n persist: true,\n anonymous: true,\n },\n groupedAuthConnectionId: {\n persist: true,\n anonymous: true,\n },\n userId: {\n persist: true,\n anonymous: true,\n },\n socialLoginEmail: {\n persist: true,\n anonymous: true,\n },\n };\n\nexport class SeedlessOnboardingController extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: VaultEncryptor;\n\n readonly #vaultOperationMutex = new Mutex();\n\n readonly toprfClient: ToprfSecureBackup;\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.network - The network to be used for the Seedless Onboarding flow.\n */\n constructor({\n messenger,\n state,\n encryptor = { encrypt, decrypt }, // default to `encrypt` and `decrypt` from `@metamask/browser-passworder`\n network = Web3AuthNetwork.Mainnet,\n }: SeedlessOnboardingControllerOptions) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: {\n ...getDefaultSeedlessOnboardingControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#vaultEncryptor = encryptor;\n this.toprfClient = new ToprfSecureBackup({\n network,\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 * You can pass this to use aggregate multiple OAuth connections. Useful when you want user to have same account while using different OAuth connections.\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n }) {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n } = params;\n const hashedIdTokenHexes = idTokens.map((idToken) => {\n return remove0x(keccak256AndHexify(stringToBytes(idToken)));\n });\n const authenticationResult = await this.toprfClient.authenticate({\n verifier: groupedAuthConnectionId || authConnectionId,\n verifierId: userId,\n idTokens: hashedIdTokenHexes,\n singleIdVerifierParams: {\n subVerifier: authConnectionId,\n subVerifierIdTokens: idTokens,\n },\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 });\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new Error(SeedlessOnboardingControllerError.AuthenticationError);\n }\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 seed phrase to backup\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 // 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 // locally evaluate the encryption key from the password\n const { encKey, authKeyPair, oprfKey } = this.toprfClient.createLocalKey({\n password,\n });\n\n // encrypt and store the seed phrase backup\n await this.#encryptAndStoreSeedPhraseBackup({\n keyringId,\n seedPhrase,\n encKey,\n authKeyPair,\n });\n\n // store/persist the encryption key shares\n // We store the seed phrase 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 rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n /**\n * Fetches all encrypted seed phrases and metadata for user's account from the metadata store.\n *\n * Decrypts the seed phrases and returns the decrypted seed phrases using the recovered encryption key from the password.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @returns A promise that resolves to the seed phrase metadata.\n */\n async fetchAllSeedPhrases(password: string): Promise<Uint8Array[]> {\n // assert that the user is authenticated before fetching the seed phrases\n this.#assertIsAuthenticatedUser(this.state);\n\n const { encKey, authKeyPair } = await this.#recoverEncKey(password);\n\n try {\n const secretData = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n\n if (secretData?.length > 0) {\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return SeedPhraseMetadata.parseSeedPhraseFromMetadataStore(secretData);\n } catch (error) {\n log('Error fetching seed phrase metadata', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToFetchSeedPhraseMetadata,\n );\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 */\n async changePassword(newPassword: string, oldPassword: string) {\n // verify the old password of the encrypted vault\n await this.#unlockVaultWithPassword(oldPassword);\n\n try {\n // update the encryption key with new password and update the Metadata Store\n const { encKey: newEncKey, authKeyPair: newAuthKeyPair } =\n await this.#changeEncryptionKey(newPassword, oldPassword);\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n } catch (error) {\n log('Error changing password', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToChangePassword);\n }\n }\n\n /**\n * Update the backup metadata state for the given seed phrase.\n *\n * @param keyringId - The keyring id of the backup seed phrase.\n * @param seedPhrase - The seed phrase to update the backup metadata for.\n */\n updateBackupMetadataState(keyringId: string, seedPhrase: Uint8Array) {\n const newBackupMetadata = {\n id: keyringId,\n hash: keccak256AndHexify(seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n }\n\n /**\n * Get the hash of the seed phrase backup for the given seed phrase, from the state.\n *\n * If the given seed phrase is not backed up and not found in the state, it will return `undefined`.\n *\n * @param seedPhrase - The seed phrase to get the hash of.\n * @returns A promise that resolves to the hash of the seed phrase backup.\n */\n getSeedPhraseBackupHash(\n seedPhrase: Uint8Array,\n ): SocialBackupsMetadata | undefined {\n const seedPhraseHash = keccak256AndHexify(seedPhrase);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === seedPhraseHash,\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(oprfKey: bigint, authPubKey: SEC1EncodedPublicKey) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n verifier,\n verifierId: this.state.userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n log('Error persisting local encryption key', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToPersistOprfKey);\n }\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(password: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n password,\n verifier,\n verifierId: this.state.userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n throw RecoveryError.getInstance(error);\n }\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey(newPassword: string, oldPassword: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n const {\n encKey,\n authKeyPair,\n keyShareIndex: newKeyShareIndex,\n } = await this.#recoverEncKey(oldPassword);\n\n return await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n verifier,\n verifierId: this.state.userId,\n oldEncKey: encKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex,\n newPassword,\n });\n }\n\n /**\n * Encrypt and store the seed phrase backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the seed phrase backup.\n * @param params.keyringId - The keyring id of the backup seed phrase.\n * @param params.seedPhrase - The seed phrase to store.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async #encryptAndStoreSeedPhraseBackup(params: {\n keyringId: string;\n seedPhrase: Uint8Array;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n }): Promise<void> {\n try {\n const { keyringId, seedPhrase, encKey, authKeyPair } = params;\n\n const seedPhraseMetadata = new SeedPhraseMetadata(seedPhrase);\n const secretData = seedPhraseMetadata.toBytes();\n await this.#withPersistedSeedPhraseBackupsState(async () => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n });\n return {\n id: keyringId,\n seedPhrase,\n };\n });\n } catch (error) {\n log('Error encrypting and storing seed phrase backup', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToEncryptAndStoreSeedPhraseBackup,\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 password - The password to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n * - nodeAuthTokens: Authentication tokens to communicate with the TOPRF service\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\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 #unlockVaultWithPassword(password: string): Promise<{\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n }> {\n return this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const encryptedVault = this.state.vault;\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerError.VaultError);\n }\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 decryptedVaultData = await this.#vaultEncryptor.decrypt(\n password,\n encryptedVault,\n );\n\n const { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair } =\n this.#parseVaultData(decryptedVaultData);\n\n // update the state with the restored nodeAuthTokens\n this.update((state) => {\n state.nodeAuthTokens = nodeAuthTokens;\n });\n\n return { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair };\n });\n }\n\n /**\n * Executes a callback function that creates or restores seed phrases and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore seed phrases\n * 2. Generates keccak256 hashes of the seed phrases\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 seed phrases to ensure their hashes are properly tracked.\n *\n * @param createSeedPhraseBackupCallback - function that returns either a single seed phrase\n * or an array of seed phrases as Uint8Array(s)\n * @returns The original seed phrase(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSeedPhraseBackupsState(\n createSeedPhraseBackupCallback: () => Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }>,\n ): Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }> {\n try {\n const backUps = await createSeedPhraseBackupCallback();\n const newBackupMetadata = {\n id: backUps.id,\n hash: keccak256AndHexify(backUps.seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n\n return backUps;\n } catch (error) {\n log('Error persisting seed phrase backups', error);\n throw error;\n }\n }\n\n #updateSocialBackupsMetadata(newSocialBackupMetadata: SocialBackupsMetadata) {\n // filter out the backed up metadata that already exists in the state\n // to prevent duplicates\n const existingBackupsMetadata = this.state.socialBackupsMetadata.find(\n (backup) => backup.id === newSocialBackupMetadata.id,\n );\n\n if (!existingBackupsMetadata) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n newSocialBackupMetadata,\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.rawToprfAuthKeyPair - The authentication key pair to encrypt the vault.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { toprfEncryptionKey, toprfAuthKeyPair } = this.#serializeKeyData(\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n );\n\n const serializedVaultData = JSON.stringify({\n authTokens: this.state.nodeAuthTokens,\n toprfEncryptionKey,\n toprfAuthKeyPair,\n });\n\n await this.#updateVault({\n password,\n serializedVaultData,\n });\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 password to encrypt the vault.\n * @param params.serializedVaultData - The serialized authentication data to update the vault with.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n serializedVaultData,\n }: {\n password: string;\n serializedVaultData: string;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {};\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 updatedState.vault = await this.#vaultEncryptor.encrypt(\n password,\n serializedVaultData,\n );\n\n this.update((state) => {\n state.vault = updatedState.vault;\n });\n });\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 /**\n * Serialize the encryption key and authentication key pair.\n *\n * @param encKey - The encryption key to serialize.\n * @param authKeyPair - The authentication key pair to serialize.\n * @returns The serialized encryption key and authentication key pair.\n */\n #serializeKeyData(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): {\n toprfEncryptionKey: string;\n toprfAuthKeyPair: string;\n } {\n const b64EncodedEncKey = bytesToBase64(encKey);\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(authKeyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(authKeyPair.pk),\n });\n\n return {\n toprfEncryptionKey: b64EncodedEncKey,\n toprfAuthKeyPair: b64EncodedAuthKeyPair,\n };\n }\n\n /**\n * Parse and deserialize the authentication data from the vault.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed authentication data.\n * @throws If the vault data is not valid.\n */\n #parseVaultData(data: unknown): {\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n } {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n this.#assertIsValidVaultData(parsedVaultData);\n\n const rawToprfEncryptionKey = base64ToBytes(\n parsedVaultData.toprfEncryptionKey,\n );\n const parsedToprfAuthKeyPair = JSON.parse(parsedVaultData.toprfAuthKeyPair);\n const rawToprfAuthKeyPair = {\n sk: BigInt(parsedToprfAuthKeyPair.sk),\n pk: base64ToBytes(parsedToprfAuthKeyPair.pk),\n };\n\n return {\n nodeAuthTokens: parsedVaultData.authTokens,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfAuthKeyPair: rawToprfAuthKeyPair,\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 if (\n !value ||\n typeof value !== 'object' ||\n !('authConnectionId' in value) ||\n typeof value.authConnectionId !== 'string' ||\n !('userId' in value) ||\n typeof value.userId !== 'string'\n ) {\n throw new Error(SeedlessOnboardingControllerError.MissingAuthUserInfo);\n }\n\n if (\n !('nodeAuthTokens' in value) ||\n typeof value.nodeAuthTokens !== 'object' ||\n !Array.isArray(value.nodeAuthTokens) ||\n value.nodeAuthTokens.length < 3 // At least 3 auth tokens are required for Threshold OPRF service\n ) {\n throw new Error(SeedlessOnboardingControllerError.InsufficientAuthToken);\n }\n }\n\n /**\n * Check if the provided value is a valid vault data.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid vault data.\n */\n #assertIsValidVaultData(value: unknown): asserts value is VaultData {\n // value is not valid vault data if any of the following conditions are true:\n if (\n !value || // value is not defined\n typeof value !== 'object' || // value is not an object\n !('authTokens' in value) || // authTokens is not defined\n typeof value.authTokens !== 'object' || // authTokens is not an object\n !('toprfEncryptionKey' in value) || // toprfEncryptionKey is not defined\n typeof value.toprfEncryptionKey !== 'string' || // toprfEncryptionKey is not a string\n !('toprfAuthKeyPair' in value) || // toprfAuthKeyPair is not defined\n typeof value.toprfAuthKeyPair !== 'string' // toprfAuthKeyPair is not a string\n ) {\n throw new Error(SeedlessOnboardingControllerError.VaultDataError);\n }\n }\n}\n\n/**\n * Assert that the provided password is a valid non-empty string.\n *\n * @param password - The password to check.\n * @throws If the password is not a valid string.\n */\nfunction assertIsValidPassword(password: unknown): asserts password is string {\n if (typeof password !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.WrongPasswordType);\n }\n\n if (!password || !password.length) {\n throw new Error(SeedlessOnboardingControllerError.InvalidEmptyPassword);\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.cjs","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { encrypt, decrypt } from '@metamask/browser-passworder';\nimport type {\n KeyPair,\n NodeAuthTokens,\n SEC1EncodedPublicKey,\n} from '@metamask/toprf-secure-backup';\nimport { ToprfSecureBackup } from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n remove0x,\n bigIntToHex,\n} from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n type AuthConnection,\n controllerName,\n SeedlessOnboardingControllerError,\n Web3AuthNetwork,\n} from './constants';\nimport { RecoveryError } from './errors';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { SeedPhraseMetadata } from './SeedPhraseMetadata';\nimport type {\n VaultEncryptor,\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerState,\n VaultData,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\n/**\n * Get the default state for the Seedless Onboarding Controller.\n *\n * @returns The default state for the Seedless Onboarding Controller.\n */\nexport function getDefaultSeedlessOnboardingControllerState(): SeedlessOnboardingControllerState {\n return {\n socialBackupsMetadata: [],\n };\n}\n\n/**\n * Seedless Onboarding Controller State Metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst seedlessOnboardingMetadata: StateMetadata<SeedlessOnboardingControllerState> =\n {\n vault: {\n persist: true,\n anonymous: false,\n },\n socialBackupsMetadata: {\n persist: true,\n anonymous: true,\n },\n nodeAuthTokens: {\n persist: false,\n anonymous: true,\n },\n authConnection: {\n persist: true,\n anonymous: true,\n },\n authConnectionId: {\n persist: true,\n anonymous: true,\n },\n groupedAuthConnectionId: {\n persist: true,\n anonymous: true,\n },\n userId: {\n persist: true,\n anonymous: true,\n },\n socialLoginEmail: {\n persist: true,\n anonymous: true,\n },\n };\n\nexport class SeedlessOnboardingController extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: VaultEncryptor;\n\n readonly #vaultOperationMutex = new Mutex();\n\n readonly toprfClient: ToprfSecureBackup;\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.network - The network to be used for the Seedless Onboarding flow.\n */\n constructor({\n messenger,\n state,\n encryptor = { encrypt, decrypt }, // default to `encrypt` and `decrypt` from `@metamask/browser-passworder`\n network = Web3AuthNetwork.Mainnet,\n }: SeedlessOnboardingControllerOptions) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: {\n ...getDefaultSeedlessOnboardingControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#vaultEncryptor = encryptor;\n this.toprfClient = new ToprfSecureBackup({\n network,\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 * You can pass this to use aggregate multiple OAuth connections. Useful when you want user to have same account while using different OAuth connections.\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n }) {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n } = params;\n const hashedIdTokenHexes = idTokens.map((idToken) => {\n return remove0x(keccak256AndHexify(stringToBytes(idToken)));\n });\n const authenticationResult = await this.toprfClient.authenticate({\n authConnectionId: groupedAuthConnectionId || authConnectionId,\n userId,\n idTokens: hashedIdTokenHexes,\n groupedAuthConnectionParams: {\n authConnectionId,\n idTokens,\n },\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 });\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new Error(SeedlessOnboardingControllerError.AuthenticationError);\n }\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 seed phrase to backup\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 // 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 // locally evaluate the encryption key from the password\n const { encKey, authKeyPair, oprfKey } = this.toprfClient.createLocalKey({\n password,\n });\n\n // encrypt and store the seed phrase backup\n await this.#encryptAndStoreSeedPhraseBackup({\n keyringId,\n seedPhrase,\n encKey,\n authKeyPair,\n });\n\n // store/persist the encryption key shares\n // We store the seed phrase 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 rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n /**\n * Fetches all encrypted seed phrases and metadata for user's account from the metadata store.\n *\n * Decrypts the seed phrases and returns the decrypted seed phrases using the recovered encryption key from the password.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @returns A promise that resolves to the seed phrase metadata.\n */\n async fetchAllSeedPhrases(password: string): Promise<Uint8Array[]> {\n // assert that the user is authenticated before fetching the seed phrases\n this.#assertIsAuthenticatedUser(this.state);\n\n const { encKey, authKeyPair } = await this.#recoverEncKey(password);\n\n try {\n const secretData = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n\n if (secretData?.length > 0) {\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return SeedPhraseMetadata.parseSeedPhraseFromMetadataStore(secretData);\n } catch (error) {\n log('Error fetching seed phrase metadata', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToFetchSeedPhraseMetadata,\n );\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 */\n async changePassword(newPassword: string, oldPassword: string) {\n // verify the old password of the encrypted vault\n await this.#unlockVaultWithPassword(oldPassword);\n\n try {\n // update the encryption key with new password and update the Metadata Store\n const { encKey: newEncKey, authKeyPair: newAuthKeyPair } =\n await this.#changeEncryptionKey(newPassword, oldPassword);\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n } catch (error) {\n log('Error changing password', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToChangePassword);\n }\n }\n\n /**\n * Update the backup metadata state for the given seed phrase.\n *\n * @param keyringId - The keyring id of the backup seed phrase.\n * @param seedPhrase - The seed phrase to update the backup metadata for.\n */\n updateBackupMetadataState(keyringId: string, seedPhrase: Uint8Array) {\n const newBackupMetadata = {\n id: keyringId,\n hash: keccak256AndHexify(seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n }\n\n /**\n * Get the hash of the seed phrase backup for the given seed phrase, from the state.\n *\n * If the given seed phrase is not backed up and not found in the state, it will return `undefined`.\n *\n * @param seedPhrase - The seed phrase to get the hash of.\n * @returns A promise that resolves to the hash of the seed phrase backup.\n */\n getSeedPhraseBackupHash(\n seedPhrase: Uint8Array,\n ): SocialBackupsMetadata | undefined {\n const seedPhraseHash = keccak256AndHexify(seedPhrase);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === seedPhraseHash,\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(oprfKey: bigint, authPubKey: SEC1EncodedPublicKey) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n userId: this.state.userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n log('Error persisting local encryption key', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToPersistOprfKey);\n }\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(password: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n password,\n authConnectionId,\n userId: this.state.userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n throw RecoveryError.getInstance(error);\n }\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey(newPassword: string, oldPassword: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n const {\n encKey,\n authKeyPair,\n keyShareIndex: newKeyShareIndex,\n } = await this.#recoverEncKey(oldPassword);\n\n return await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n userId: this.state.userId,\n oldEncKey: encKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex,\n oldPassword,\n newPassword,\n });\n }\n\n /**\n * Encrypt and store the seed phrase backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the seed phrase backup.\n * @param params.keyringId - The keyring id of the backup seed phrase.\n * @param params.seedPhrase - The seed phrase to store.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async #encryptAndStoreSeedPhraseBackup(params: {\n keyringId: string;\n seedPhrase: Uint8Array;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n }): Promise<void> {\n try {\n const { keyringId, seedPhrase, encKey, authKeyPair } = params;\n\n const seedPhraseMetadata = new SeedPhraseMetadata(seedPhrase);\n const secretData = seedPhraseMetadata.toBytes();\n await this.#withPersistedSeedPhraseBackupsState(async () => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n });\n return {\n id: keyringId,\n seedPhrase,\n };\n });\n } catch (error) {\n log('Error encrypting and storing seed phrase backup', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToEncryptAndStoreSeedPhraseBackup,\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 password - The password to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n * - nodeAuthTokens: Authentication tokens to communicate with the TOPRF service\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\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 #unlockVaultWithPassword(password: string): Promise<{\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n }> {\n return this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const encryptedVault = this.state.vault;\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerError.VaultError);\n }\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 decryptedVaultData = await this.#vaultEncryptor.decrypt(\n password,\n encryptedVault,\n );\n\n const { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair } =\n this.#parseVaultData(decryptedVaultData);\n\n // update the state with the restored nodeAuthTokens\n this.update((state) => {\n state.nodeAuthTokens = nodeAuthTokens;\n });\n\n return { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair };\n });\n }\n\n /**\n * Executes a callback function that creates or restores seed phrases and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore seed phrases\n * 2. Generates keccak256 hashes of the seed phrases\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 seed phrases to ensure their hashes are properly tracked.\n *\n * @param createSeedPhraseBackupCallback - function that returns either a single seed phrase\n * or an array of seed phrases as Uint8Array(s)\n * @returns The original seed phrase(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSeedPhraseBackupsState(\n createSeedPhraseBackupCallback: () => Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }>,\n ): Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }> {\n try {\n const backUps = await createSeedPhraseBackupCallback();\n const newBackupMetadata = {\n id: backUps.id,\n hash: keccak256AndHexify(backUps.seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n\n return backUps;\n } catch (error) {\n log('Error persisting seed phrase backups', error);\n throw error;\n }\n }\n\n #updateSocialBackupsMetadata(newSocialBackupMetadata: SocialBackupsMetadata) {\n // filter out the backed up metadata that already exists in the state\n // to prevent duplicates\n const existingBackupsMetadata = this.state.socialBackupsMetadata.find(\n (backup) => backup.id === newSocialBackupMetadata.id,\n );\n\n if (!existingBackupsMetadata) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n newSocialBackupMetadata,\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.rawToprfAuthKeyPair - The authentication key pair to encrypt the vault.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { toprfEncryptionKey, toprfAuthKeyPair } = this.#serializeKeyData(\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n );\n\n const serializedVaultData = JSON.stringify({\n authTokens: this.state.nodeAuthTokens,\n toprfEncryptionKey,\n toprfAuthKeyPair,\n });\n\n await this.#updateVault({\n password,\n serializedVaultData,\n });\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 password to encrypt the vault.\n * @param params.serializedVaultData - The serialized authentication data to update the vault with.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n serializedVaultData,\n }: {\n password: string;\n serializedVaultData: string;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {};\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 updatedState.vault = await this.#vaultEncryptor.encrypt(\n password,\n serializedVaultData,\n );\n\n this.update((state) => {\n state.vault = updatedState.vault;\n });\n });\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 /**\n * Serialize the encryption key and authentication key pair.\n *\n * @param encKey - The encryption key to serialize.\n * @param authKeyPair - The authentication key pair to serialize.\n * @returns The serialized encryption key and authentication key pair.\n */\n #serializeKeyData(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): {\n toprfEncryptionKey: string;\n toprfAuthKeyPair: string;\n } {\n const b64EncodedEncKey = bytesToBase64(encKey);\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(authKeyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(authKeyPair.pk),\n });\n\n return {\n toprfEncryptionKey: b64EncodedEncKey,\n toprfAuthKeyPair: b64EncodedAuthKeyPair,\n };\n }\n\n /**\n * Parse and deserialize the authentication data from the vault.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed authentication data.\n * @throws If the vault data is not valid.\n */\n #parseVaultData(data: unknown): {\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n } {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n this.#assertIsValidVaultData(parsedVaultData);\n\n const rawToprfEncryptionKey = base64ToBytes(\n parsedVaultData.toprfEncryptionKey,\n );\n const parsedToprfAuthKeyPair = JSON.parse(parsedVaultData.toprfAuthKeyPair);\n const rawToprfAuthKeyPair = {\n sk: BigInt(parsedToprfAuthKeyPair.sk),\n pk: base64ToBytes(parsedToprfAuthKeyPair.pk),\n };\n\n return {\n nodeAuthTokens: parsedVaultData.authTokens,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfAuthKeyPair: rawToprfAuthKeyPair,\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 if (\n !value ||\n typeof value !== 'object' ||\n !('authConnectionId' in value) ||\n typeof value.authConnectionId !== 'string' ||\n !('userId' in value) ||\n typeof value.userId !== 'string'\n ) {\n throw new Error(SeedlessOnboardingControllerError.MissingAuthUserInfo);\n }\n\n if (\n !('nodeAuthTokens' in value) ||\n typeof value.nodeAuthTokens !== 'object' ||\n !Array.isArray(value.nodeAuthTokens) ||\n value.nodeAuthTokens.length < 3 // At least 3 auth tokens are required for Threshold OPRF service\n ) {\n throw new Error(SeedlessOnboardingControllerError.InsufficientAuthToken);\n }\n }\n\n /**\n * Check if the provided value is a valid vault data.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid vault data.\n */\n #assertIsValidVaultData(value: unknown): asserts value is VaultData {\n // value is not valid vault data if any of the following conditions are true:\n if (\n !value || // value is not defined\n typeof value !== 'object' || // value is not an object\n !('authTokens' in value) || // authTokens is not defined\n typeof value.authTokens !== 'object' || // authTokens is not an object\n !('toprfEncryptionKey' in value) || // toprfEncryptionKey is not defined\n typeof value.toprfEncryptionKey !== 'string' || // toprfEncryptionKey is not a string\n !('toprfAuthKeyPair' in value) || // toprfAuthKeyPair is not defined\n typeof value.toprfAuthKeyPair !== 'string' // toprfAuthKeyPair is not a string\n ) {\n throw new Error(SeedlessOnboardingControllerError.VaultDataError);\n }\n }\n}\n\n/**\n * Assert that the provided password is a valid non-empty string.\n *\n * @param password - The password to check.\n * @throws If the password is not a valid string.\n */\nfunction assertIsValidPassword(password: unknown): asserts password is string {\n if (typeof password !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.WrongPasswordType);\n }\n\n if (!password || !password.length) {\n throw new Error(SeedlessOnboardingControllerError.InvalidEmptyPassword);\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 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.d.cts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAO3D,OAAO,EAAE,iBAAiB,EAAE,sCAAsC;AAUlE,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EAGf,wBAAoB;AAIrB,OAAO,KAAK,EAGV,qCAAqC,EACrC,mCAAmC,EACnC,iCAAiC,EAGjC,qBAAqB,EACtB,oBAAgB;AAIjB;;;;GAIG;AACH,wBAAgB,2CAA2C,IAAI,iCAAiC,CAI/F;AA6CD,qBAAa,4BAA6B,SAAQ,cAAc,CAC9D,OAAO,cAAc,EACrB,iCAAiC,EACjC,qCAAqC,CACtC;;IAKC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAExC;;;;;;;;OAQG;gBACS,EACV,SAAS,EACT,KAAK,EACL,SAAgC,EAAE,yEAAyE;IAC3G,OAAiC,GAClC,EAAE,mCAAmC;IAiBtC;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,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;KAC3B;IAsCD;;;;;;;OAOG;IACG,iCAAiC,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;;OAOG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA6BlE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAqB7D;;;;;OAKG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;IASnE;;;;;;;OAOG;IACH,uBAAuB,CACrB,UAAU,EAAE,UAAU,GACrB,qBAAqB,GAAG,SAAS;CA+brC"}
1
+ {"version":3,"file":"SeedlessOnboardingController.d.cts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAO3D,OAAO,EAAE,iBAAiB,EAAE,sCAAsC;AAUlE,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EAGf,wBAAoB;AAIrB,OAAO,KAAK,EAGV,qCAAqC,EACrC,mCAAmC,EACnC,iCAAiC,EAGjC,qBAAqB,EACtB,oBAAgB;AAIjB;;;;GAIG;AACH,wBAAgB,2CAA2C,IAAI,iCAAiC,CAI/F;AA6CD,qBAAa,4BAA6B,SAAQ,cAAc,CAC9D,OAAO,cAAc,EACrB,iCAAiC,EACjC,qCAAqC,CACtC;;IAKC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAExC;;;;;;;;OAQG;gBACS,EACV,SAAS,EACT,KAAK,EACL,SAAgC,EAAE,yEAAyE;IAC3G,OAAiC,GAClC,EAAE,mCAAmC;IAiBtC;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,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;KAC3B;IAsCD;;;;;;;OAOG;IACG,iCAAiC,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;;OAOG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA6BlE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAqB7D;;;;;OAKG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;IASnE;;;;;;;OAOG;IACH,uBAAuB,CACrB,UAAU,EAAE,UAAU,GACrB,qBAAqB,GAAG,SAAS;CAgcrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.d.mts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAO3D,OAAO,EAAE,iBAAiB,EAAE,sCAAsC;AAUlE,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EAGf,wBAAoB;AAIrB,OAAO,KAAK,EAGV,qCAAqC,EACrC,mCAAmC,EACnC,iCAAiC,EAGjC,qBAAqB,EACtB,oBAAgB;AAIjB;;;;GAIG;AACH,wBAAgB,2CAA2C,IAAI,iCAAiC,CAI/F;AA6CD,qBAAa,4BAA6B,SAAQ,cAAc,CAC9D,OAAO,cAAc,EACrB,iCAAiC,EACjC,qCAAqC,CACtC;;IAKC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAExC;;;;;;;;OAQG;gBACS,EACV,SAAS,EACT,KAAK,EACL,SAAgC,EAAE,yEAAyE;IAC3G,OAAiC,GAClC,EAAE,mCAAmC;IAiBtC;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,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;KAC3B;IAsCD;;;;;;;OAOG;IACG,iCAAiC,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;;OAOG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA6BlE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAqB7D;;;;;OAKG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;IASnE;;;;;;;OAOG;IACH,uBAAuB,CACrB,UAAU,EAAE,UAAU,GACrB,qBAAqB,GAAG,SAAS;CA+brC"}
1
+ {"version":3,"file":"SeedlessOnboardingController.d.mts","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAO3D,OAAO,EAAE,iBAAiB,EAAE,sCAAsC;AAUlE,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EAGf,wBAAoB;AAIrB,OAAO,KAAK,EAGV,qCAAqC,EACrC,mCAAmC,EACnC,iCAAiC,EAGjC,qBAAqB,EACtB,oBAAgB;AAIjB;;;;GAIG;AACH,wBAAgB,2CAA2C,IAAI,iCAAiC,CAI/F;AA6CD,qBAAa,4BAA6B,SAAQ,cAAc,CAC9D,OAAO,cAAc,EACrB,iCAAiC,EACjC,qCAAqC,CACtC;;IAKC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAExC;;;;;;;;OAQG;gBACS,EACV,SAAS,EACT,KAAK,EACL,SAAgC,EAAE,yEAAyE;IAC3G,OAAiC,GAClC,EAAE,mCAAmC;IAiBtC;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,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;KAC3B;IAsCD;;;;;;;OAOG;IACG,iCAAiC,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;;OAOG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA6BlE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAqB7D;;;;;OAKG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;IASnE;;;;;;;OAOG;IACH,uBAAuB,CACrB,UAAU,EAAE,UAAU,GACrB,qBAAqB,GAAG,SAAS;CAgcrC"}
@@ -122,12 +122,12 @@ export class SeedlessOnboardingController extends BaseController {
122
122
  return remove0x(keccak256AndHexify(stringToBytes(idToken)));
123
123
  });
124
124
  const authenticationResult = await this.toprfClient.authenticate({
125
- verifier: groupedAuthConnectionId || authConnectionId,
126
- verifierId: userId,
125
+ authConnectionId: groupedAuthConnectionId || authConnectionId,
126
+ userId,
127
127
  idTokens: hashedIdTokenHexes,
128
- singleIdVerifierParams: {
129
- subVerifier: authConnectionId,
130
- subVerifierIdTokens: idTokens,
128
+ groupedAuthConnectionParams: {
129
+ authConnectionId,
130
+ idTokens,
131
131
  },
132
132
  });
133
133
  // update the state with the authenticated user info
@@ -274,12 +274,12 @@ _SeedlessOnboardingController_vaultEncryptor = new WeakMap(), _SeedlessOnboardin
274
274
  */
275
275
  async function _SeedlessOnboardingController_persistOprfKey(oprfKey, authPubKey) {
276
276
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
277
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
277
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
278
278
  try {
279
279
  await this.toprfClient.persistLocalKey({
280
280
  nodeAuthTokens: this.state.nodeAuthTokens,
281
- verifier,
282
- verifierId: this.state.userId,
281
+ authConnectionId,
282
+ userId: this.state.userId,
283
283
  oprfKey,
284
284
  authPubKey,
285
285
  });
@@ -298,13 +298,13 @@ async function _SeedlessOnboardingController_persistOprfKey(oprfKey, authPubKey)
298
298
  */
299
299
  async function _SeedlessOnboardingController_recoverEncKey(password) {
300
300
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
301
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
301
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
302
302
  try {
303
303
  const recoverEncKeyResult = await this.toprfClient.recoverEncKey({
304
304
  nodeAuthTokens: this.state.nodeAuthTokens,
305
305
  password,
306
- verifier,
307
- verifierId: this.state.userId,
306
+ authConnectionId,
307
+ userId: this.state.userId,
308
308
  });
309
309
  return recoverEncKeyResult;
310
310
  }
@@ -321,15 +321,16 @@ async function _SeedlessOnboardingController_recoverEncKey(password) {
321
321
  */
322
322
  async function _SeedlessOnboardingController_changeEncryptionKey(newPassword, oldPassword) {
323
323
  __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_assertIsAuthenticatedUser).call(this, this.state);
324
- const verifier = this.state.groupedAuthConnectionId || this.state.authConnectionId;
324
+ const authConnectionId = this.state.groupedAuthConnectionId || this.state.authConnectionId;
325
325
  const { encKey, authKeyPair, keyShareIndex: newKeyShareIndex, } = await __classPrivateFieldGet(this, _SeedlessOnboardingController_instances, "m", _SeedlessOnboardingController_recoverEncKey).call(this, oldPassword);
326
326
  return await this.toprfClient.changeEncKey({
327
327
  nodeAuthTokens: this.state.nodeAuthTokens,
328
- verifier,
329
- verifierId: this.state.userId,
328
+ authConnectionId,
329
+ userId: this.state.userId,
330
330
  oldEncKey: encKey,
331
331
  oldAuthKeyPair: authKeyPair,
332
332
  newKeyShareIndex,
333
+ oldPassword,
333
334
  newPassword,
334
335
  });
335
336
  }, _SeedlessOnboardingController_encryptAndStoreSeedPhraseBackup =
@@ -1 +1 @@
1
- {"version":3,"file":"SeedlessOnboardingController.mjs","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { encrypt, decrypt } from '@metamask/browser-passworder';\nimport type {\n KeyPair,\n NodeAuthTokens,\n SEC1EncodedPublicKey,\n} from '@metamask/toprf-secure-backup';\nimport { ToprfSecureBackup } from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n remove0x,\n bigIntToHex,\n} from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n type AuthConnection,\n controllerName,\n SeedlessOnboardingControllerError,\n Web3AuthNetwork,\n} from './constants';\nimport { RecoveryError } from './errors';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { SeedPhraseMetadata } from './SeedPhraseMetadata';\nimport type {\n VaultEncryptor,\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerState,\n VaultData,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\n/**\n * Get the default state for the Seedless Onboarding Controller.\n *\n * @returns The default state for the Seedless Onboarding Controller.\n */\nexport function getDefaultSeedlessOnboardingControllerState(): SeedlessOnboardingControllerState {\n return {\n socialBackupsMetadata: [],\n };\n}\n\n/**\n * Seedless Onboarding Controller State Metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst seedlessOnboardingMetadata: StateMetadata<SeedlessOnboardingControllerState> =\n {\n vault: {\n persist: true,\n anonymous: false,\n },\n socialBackupsMetadata: {\n persist: true,\n anonymous: true,\n },\n nodeAuthTokens: {\n persist: false,\n anonymous: true,\n },\n authConnection: {\n persist: true,\n anonymous: true,\n },\n authConnectionId: {\n persist: true,\n anonymous: true,\n },\n groupedAuthConnectionId: {\n persist: true,\n anonymous: true,\n },\n userId: {\n persist: true,\n anonymous: true,\n },\n socialLoginEmail: {\n persist: true,\n anonymous: true,\n },\n };\n\nexport class SeedlessOnboardingController extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: VaultEncryptor;\n\n readonly #vaultOperationMutex = new Mutex();\n\n readonly toprfClient: ToprfSecureBackup;\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.network - The network to be used for the Seedless Onboarding flow.\n */\n constructor({\n messenger,\n state,\n encryptor = { encrypt, decrypt }, // default to `encrypt` and `decrypt` from `@metamask/browser-passworder`\n network = Web3AuthNetwork.Mainnet,\n }: SeedlessOnboardingControllerOptions) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: {\n ...getDefaultSeedlessOnboardingControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#vaultEncryptor = encryptor;\n this.toprfClient = new ToprfSecureBackup({\n network,\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 * You can pass this to use aggregate multiple OAuth connections. Useful when you want user to have same account while using different OAuth connections.\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n }) {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n } = params;\n const hashedIdTokenHexes = idTokens.map((idToken) => {\n return remove0x(keccak256AndHexify(stringToBytes(idToken)));\n });\n const authenticationResult = await this.toprfClient.authenticate({\n verifier: groupedAuthConnectionId || authConnectionId,\n verifierId: userId,\n idTokens: hashedIdTokenHexes,\n singleIdVerifierParams: {\n subVerifier: authConnectionId,\n subVerifierIdTokens: idTokens,\n },\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 });\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new Error(SeedlessOnboardingControllerError.AuthenticationError);\n }\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 seed phrase to backup\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 // 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 // locally evaluate the encryption key from the password\n const { encKey, authKeyPair, oprfKey } = this.toprfClient.createLocalKey({\n password,\n });\n\n // encrypt and store the seed phrase backup\n await this.#encryptAndStoreSeedPhraseBackup({\n keyringId,\n seedPhrase,\n encKey,\n authKeyPair,\n });\n\n // store/persist the encryption key shares\n // We store the seed phrase 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 rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n /**\n * Fetches all encrypted seed phrases and metadata for user's account from the metadata store.\n *\n * Decrypts the seed phrases and returns the decrypted seed phrases using the recovered encryption key from the password.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @returns A promise that resolves to the seed phrase metadata.\n */\n async fetchAllSeedPhrases(password: string): Promise<Uint8Array[]> {\n // assert that the user is authenticated before fetching the seed phrases\n this.#assertIsAuthenticatedUser(this.state);\n\n const { encKey, authKeyPair } = await this.#recoverEncKey(password);\n\n try {\n const secretData = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n\n if (secretData?.length > 0) {\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return SeedPhraseMetadata.parseSeedPhraseFromMetadataStore(secretData);\n } catch (error) {\n log('Error fetching seed phrase metadata', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToFetchSeedPhraseMetadata,\n );\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 */\n async changePassword(newPassword: string, oldPassword: string) {\n // verify the old password of the encrypted vault\n await this.#unlockVaultWithPassword(oldPassword);\n\n try {\n // update the encryption key with new password and update the Metadata Store\n const { encKey: newEncKey, authKeyPair: newAuthKeyPair } =\n await this.#changeEncryptionKey(newPassword, oldPassword);\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n } catch (error) {\n log('Error changing password', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToChangePassword);\n }\n }\n\n /**\n * Update the backup metadata state for the given seed phrase.\n *\n * @param keyringId - The keyring id of the backup seed phrase.\n * @param seedPhrase - The seed phrase to update the backup metadata for.\n */\n updateBackupMetadataState(keyringId: string, seedPhrase: Uint8Array) {\n const newBackupMetadata = {\n id: keyringId,\n hash: keccak256AndHexify(seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n }\n\n /**\n * Get the hash of the seed phrase backup for the given seed phrase, from the state.\n *\n * If the given seed phrase is not backed up and not found in the state, it will return `undefined`.\n *\n * @param seedPhrase - The seed phrase to get the hash of.\n * @returns A promise that resolves to the hash of the seed phrase backup.\n */\n getSeedPhraseBackupHash(\n seedPhrase: Uint8Array,\n ): SocialBackupsMetadata | undefined {\n const seedPhraseHash = keccak256AndHexify(seedPhrase);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === seedPhraseHash,\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(oprfKey: bigint, authPubKey: SEC1EncodedPublicKey) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n verifier,\n verifierId: this.state.userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n log('Error persisting local encryption key', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToPersistOprfKey);\n }\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(password: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n password,\n verifier,\n verifierId: this.state.userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n throw RecoveryError.getInstance(error);\n }\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey(newPassword: string, oldPassword: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const verifier =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n const {\n encKey,\n authKeyPair,\n keyShareIndex: newKeyShareIndex,\n } = await this.#recoverEncKey(oldPassword);\n\n return await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n verifier,\n verifierId: this.state.userId,\n oldEncKey: encKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex,\n newPassword,\n });\n }\n\n /**\n * Encrypt and store the seed phrase backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the seed phrase backup.\n * @param params.keyringId - The keyring id of the backup seed phrase.\n * @param params.seedPhrase - The seed phrase to store.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async #encryptAndStoreSeedPhraseBackup(params: {\n keyringId: string;\n seedPhrase: Uint8Array;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n }): Promise<void> {\n try {\n const { keyringId, seedPhrase, encKey, authKeyPair } = params;\n\n const seedPhraseMetadata = new SeedPhraseMetadata(seedPhrase);\n const secretData = seedPhraseMetadata.toBytes();\n await this.#withPersistedSeedPhraseBackupsState(async () => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n });\n return {\n id: keyringId,\n seedPhrase,\n };\n });\n } catch (error) {\n log('Error encrypting and storing seed phrase backup', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToEncryptAndStoreSeedPhraseBackup,\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 password - The password to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n * - nodeAuthTokens: Authentication tokens to communicate with the TOPRF service\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\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 #unlockVaultWithPassword(password: string): Promise<{\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n }> {\n return this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const encryptedVault = this.state.vault;\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerError.VaultError);\n }\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 decryptedVaultData = await this.#vaultEncryptor.decrypt(\n password,\n encryptedVault,\n );\n\n const { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair } =\n this.#parseVaultData(decryptedVaultData);\n\n // update the state with the restored nodeAuthTokens\n this.update((state) => {\n state.nodeAuthTokens = nodeAuthTokens;\n });\n\n return { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair };\n });\n }\n\n /**\n * Executes a callback function that creates or restores seed phrases and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore seed phrases\n * 2. Generates keccak256 hashes of the seed phrases\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 seed phrases to ensure their hashes are properly tracked.\n *\n * @param createSeedPhraseBackupCallback - function that returns either a single seed phrase\n * or an array of seed phrases as Uint8Array(s)\n * @returns The original seed phrase(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSeedPhraseBackupsState(\n createSeedPhraseBackupCallback: () => Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }>,\n ): Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }> {\n try {\n const backUps = await createSeedPhraseBackupCallback();\n const newBackupMetadata = {\n id: backUps.id,\n hash: keccak256AndHexify(backUps.seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n\n return backUps;\n } catch (error) {\n log('Error persisting seed phrase backups', error);\n throw error;\n }\n }\n\n #updateSocialBackupsMetadata(newSocialBackupMetadata: SocialBackupsMetadata) {\n // filter out the backed up metadata that already exists in the state\n // to prevent duplicates\n const existingBackupsMetadata = this.state.socialBackupsMetadata.find(\n (backup) => backup.id === newSocialBackupMetadata.id,\n );\n\n if (!existingBackupsMetadata) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n newSocialBackupMetadata,\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.rawToprfAuthKeyPair - The authentication key pair to encrypt the vault.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { toprfEncryptionKey, toprfAuthKeyPair } = this.#serializeKeyData(\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n );\n\n const serializedVaultData = JSON.stringify({\n authTokens: this.state.nodeAuthTokens,\n toprfEncryptionKey,\n toprfAuthKeyPair,\n });\n\n await this.#updateVault({\n password,\n serializedVaultData,\n });\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 password to encrypt the vault.\n * @param params.serializedVaultData - The serialized authentication data to update the vault with.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n serializedVaultData,\n }: {\n password: string;\n serializedVaultData: string;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {};\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 updatedState.vault = await this.#vaultEncryptor.encrypt(\n password,\n serializedVaultData,\n );\n\n this.update((state) => {\n state.vault = updatedState.vault;\n });\n });\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 /**\n * Serialize the encryption key and authentication key pair.\n *\n * @param encKey - The encryption key to serialize.\n * @param authKeyPair - The authentication key pair to serialize.\n * @returns The serialized encryption key and authentication key pair.\n */\n #serializeKeyData(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): {\n toprfEncryptionKey: string;\n toprfAuthKeyPair: string;\n } {\n const b64EncodedEncKey = bytesToBase64(encKey);\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(authKeyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(authKeyPair.pk),\n });\n\n return {\n toprfEncryptionKey: b64EncodedEncKey,\n toprfAuthKeyPair: b64EncodedAuthKeyPair,\n };\n }\n\n /**\n * Parse and deserialize the authentication data from the vault.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed authentication data.\n * @throws If the vault data is not valid.\n */\n #parseVaultData(data: unknown): {\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n } {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n this.#assertIsValidVaultData(parsedVaultData);\n\n const rawToprfEncryptionKey = base64ToBytes(\n parsedVaultData.toprfEncryptionKey,\n );\n const parsedToprfAuthKeyPair = JSON.parse(parsedVaultData.toprfAuthKeyPair);\n const rawToprfAuthKeyPair = {\n sk: BigInt(parsedToprfAuthKeyPair.sk),\n pk: base64ToBytes(parsedToprfAuthKeyPair.pk),\n };\n\n return {\n nodeAuthTokens: parsedVaultData.authTokens,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfAuthKeyPair: rawToprfAuthKeyPair,\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 if (\n !value ||\n typeof value !== 'object' ||\n !('authConnectionId' in value) ||\n typeof value.authConnectionId !== 'string' ||\n !('userId' in value) ||\n typeof value.userId !== 'string'\n ) {\n throw new Error(SeedlessOnboardingControllerError.MissingAuthUserInfo);\n }\n\n if (\n !('nodeAuthTokens' in value) ||\n typeof value.nodeAuthTokens !== 'object' ||\n !Array.isArray(value.nodeAuthTokens) ||\n value.nodeAuthTokens.length < 3 // At least 3 auth tokens are required for Threshold OPRF service\n ) {\n throw new Error(SeedlessOnboardingControllerError.InsufficientAuthToken);\n }\n }\n\n /**\n * Check if the provided value is a valid vault data.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid vault data.\n */\n #assertIsValidVaultData(value: unknown): asserts value is VaultData {\n // value is not valid vault data if any of the following conditions are true:\n if (\n !value || // value is not defined\n typeof value !== 'object' || // value is not an object\n !('authTokens' in value) || // authTokens is not defined\n typeof value.authTokens !== 'object' || // authTokens is not an object\n !('toprfEncryptionKey' in value) || // toprfEncryptionKey is not defined\n typeof value.toprfEncryptionKey !== 'string' || // toprfEncryptionKey is not a string\n !('toprfAuthKeyPair' in value) || // toprfAuthKeyPair is not defined\n typeof value.toprfAuthKeyPair !== 'string' // toprfAuthKeyPair is not a string\n ) {\n throw new Error(SeedlessOnboardingControllerError.VaultDataError);\n }\n }\n}\n\n/**\n * Assert that the provided password is a valid non-empty string.\n *\n * @param password - The password to check.\n * @throws If the password is not a valid string.\n */\nfunction assertIsValidPassword(password: unknown): asserts password is string {\n if (typeof password !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.WrongPasswordType);\n }\n\n if (!password || !password.length) {\n throw new Error(SeedlessOnboardingControllerError.InvalidEmptyPassword);\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.mjs","sourceRoot":"","sources":["../src/SeedlessOnboardingController.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAE,qCAAqC;AAElE,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qCAAqC;AAMhE,OAAO,EAAE,iBAAiB,EAAE,sCAAsC;AAClE,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,QAAQ,EACR,WAAW,EACZ,wBAAwB;AACzB,OAAO,EAAE,KAAK,EAAE,oBAAoB;AAEpC,OAAO,EAEL,cAAc,EACd,iCAAiC,EACjC,eAAe,EAChB,wBAAoB;AACrB,OAAO,EAAE,aAAa,EAAE,qBAAiB;AACzC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,qBAAiB;AAC7D,OAAO,EAAE,kBAAkB,EAAE,iCAA6B;AAY1D,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,2CAA2C;IACzD,OAAO;QACL,qBAAqB,EAAE,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,0BAA0B,GAC9B;IACE,KAAK,EAAE;QACL,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;IACD,cAAc,EAAE;QACd,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI;KAChB;IACD,cAAc,EAAE;QACd,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;IACD,gBAAgB,EAAE;QAChB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;IACD,uBAAuB,EAAE;QACvB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;IACD,gBAAgB,EAAE;QAChB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;KAChB;CACF,CAAC;AAEJ,MAAM,OAAO,4BAA6B,SAAQ,cAIjD;IAOC;;;;;;;;OAQG;IACH,YAAY,EACV,SAAS,EACT,KAAK,EACL,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,yEAAyE;IAC3G,OAAO,GAAG,eAAe,CAAC,OAAO,GACG;QACpC,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,0BAA0B;YACpC,KAAK,EAAE;gBACL,GAAG,2CAA2C,EAAE;gBAChD,GAAG,KAAK;aACT;YACD,SAAS;SACV,CAAC,CAAC;;QA7BI,+DAAgC;QAEhC,4DAAuB,IAAI,KAAK,EAAE,EAAC;QA6B1C,uBAAA,IAAI,gDAAmB,SAAS,MAAA,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,IAAI,iBAAiB,CAAC;YACvC,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,YAAY,CAAC,MAOlB;QACC,IAAI;YACF,MAAM,EACJ,QAAQ,EACR,gBAAgB,EAChB,uBAAuB,EACvB,MAAM,EACN,cAAc,EACd,gBAAgB,GACjB,GAAG,MAAM,CAAC;YACX,MAAM,kBAAkB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAClD,OAAO,QAAQ,CAAC,kBAAkB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;YACH,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;gBAC/D,gBAAgB,EAAE,uBAAuB,IAAI,gBAAgB;gBAC7D,MAAM;gBACN,QAAQ,EAAE,kBAAkB;gBAC5B,2BAA2B,EAAE;oBAC3B,gBAAgB;oBAChB,QAAQ;iBACT;aACF,CAAC,CAAC;YACH,oDAAoD;YACpD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,cAAc,GAAG,oBAAoB,CAAC,cAAc,CAAC;gBAC3D,KAAK,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;gBAC1C,KAAK,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBACtB,KAAK,CAAC,cAAc,GAAG,cAAc,CAAC;gBACtC,KAAK,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;YAC5C,CAAC,CAAC,CAAC;YACH,OAAO,oBAAoB,CAAC;SAC7B;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,mBAAmB,CAAC,CAAC;SACxE;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,iCAAiC,CACrC,QAAgB,EAChB,UAAsB,EACtB,SAAiB;QAEjB,+BAA+B;QAC/B,qGAAqG;QACrG,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;QAE5C,wDAAwD;QACxD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;YACvE,QAAQ;SACT,CAAC,CAAC;QAEH,2CAA2C;QAC3C,MAAM,uBAAA,IAAI,8GAAiC,MAArC,IAAI,EAAkC;YAC1C,SAAS;YACT,UAAU;YACV,MAAM;YACN,WAAW;SACZ,CAAC,CAAC;QAEH,0CAA0C;QAC1C,0FAA0F;QAC1F,4FAA4F;QAC5F,kDAAkD;QAClD,MAAM,uBAAA,IAAI,6FAAgB,MAApB,IAAI,EAAiB,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;QACpD,4DAA4D;QAC5D,MAAM,uBAAA,IAAI,yGAA4B,MAAhC,IAAI,EAA6B;YACrC,QAAQ;YACR,qBAAqB,EAAE,MAAM;YAC7B,mBAAmB,EAAE,WAAW;SACjC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,mBAAmB,CAAC,QAAgB;QACxC,yEAAyE;QACzE,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;QAE5C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,uBAAA,IAAI,4FAAe,MAAnB,IAAI,EAAgB,QAAQ,CAAC,CAAC;QAEpE,IAAI;YACF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,uBAAuB,CAAC;gBAChE,MAAM,EAAE,MAAM;gBACd,WAAW;aACZ,CAAC,CAAC;YAEH,IAAI,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE;gBAC1B,MAAM,uBAAA,IAAI,yGAA4B,MAAhC,IAAI,EAA6B;oBACrC,QAAQ;oBACR,qBAAqB,EAAE,MAAM;oBAC7B,mBAAmB,EAAE,WAAW;iBACjC,CAAC,CAAC;aACJ;YAED,OAAO,kBAAkB,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC;SACxE;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,iCAAiC,CAAC,+BAA+B,CAClE,CAAC;SACH;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,cAAc,CAAC,WAAmB,EAAE,WAAmB;QAC3D,iDAAiD;QACjD,MAAM,uBAAA,IAAI,sGAAyB,MAA7B,IAAI,EAA0B,WAAW,CAAC,CAAC;QAEjD,IAAI;YACF,4EAA4E;YAC5E,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,GACtD,MAAM,uBAAA,IAAI,kGAAqB,MAAzB,IAAI,EAAsB,WAAW,EAAE,WAAW,CAAC,CAAC;YAE5D,iDAAiD;YACjD,MAAM,uBAAA,IAAI,yGAA4B,MAAhC,IAAI,EAA6B;gBACrC,QAAQ,EAAE,WAAW;gBACrB,qBAAqB,EAAE,SAAS;gBAChC,mBAAmB,EAAE,cAAc;aACpC,CAAC,CAAC;SACJ;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,sBAAsB,CAAC,CAAC;SAC3E;IACH,CAAC;IAED;;;;;OAKG;IACH,yBAAyB,CAAC,SAAiB,EAAE,UAAsB;QACjE,MAAM,iBAAiB,GAAG;YACxB,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,kBAAkB,CAAC,UAAU,CAAC;SACrC,CAAC;QAEF,uBAAA,IAAI,0GAA6B,MAAjC,IAAI,EAA8B,iBAAiB,CAAC,CAAC;IACvD,CAAC;IAED;;;;;;;OAOG;IACH,uBAAuB,CACrB,UAAsB;QAEtB,MAAM,cAAc,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAC1C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAC3C,CAAC;IACJ,CAAC;CA2bF;;AAzbC;;;;;;GAMG;AACH,KAAK,uDAAiB,OAAe,EAAE,UAAgC;IACrE,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GACpB,IAAI,CAAC,KAAK,CAAC,uBAAuB,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;IAEpE,IAAI;QACF,MAAM,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC;YACrC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;YACzC,gBAAgB;YAChB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YACzB,OAAO;YACP,UAAU;SACX,CAAC,CAAC;KACJ;IAAC,OAAO,KAAK,EAAE;QACd,GAAG,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,sBAAsB,CAAC,CAAC;KAC3E;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,sDAAgB,QAAgB;IACnC,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GACpB,IAAI,CAAC,KAAK,CAAC,uBAAuB,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;IAEpE,IAAI;QACF,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC;YAC/D,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;YACzC,QAAQ;YACR,gBAAgB;YAChB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC;KAC5B;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;KACxC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,4DAAsB,WAAmB,EAAE,WAAmB;IACjE,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GACpB,IAAI,CAAC,KAAK,CAAC,uBAAuB,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;IAEpE,MAAM,EACJ,MAAM,EACN,WAAW,EACX,aAAa,EAAE,gBAAgB,GAChC,GAAG,MAAM,uBAAA,IAAI,4FAAe,MAAnB,IAAI,EAAgB,WAAW,CAAC,CAAC;IAE3C,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;QACzC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;QACzC,gBAAgB;QAChB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;QACzB,SAAS,EAAE,MAAM;QACjB,cAAc,EAAE,WAAW;QAC3B,gBAAgB;QAChB,WAAW;QACX,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,wEAAkC,MAKtC;IACC,IAAI;QACF,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;QAE9D,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,uBAAA,IAAI,kHAAqC,MAAzC,IAAI,EAAsC,KAAK,IAAI,EAAE;YACzD,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;gBACvC,MAAM;gBACN,UAAU;gBACV,WAAW;aACZ,CAAC,CAAC;YACH,OAAO;gBACL,EAAE,EAAE,SAAS;gBACb,UAAU;aACX,CAAC;QACJ,CAAC,CAAC,CAAC;KACJ;IAAC,OAAO,KAAK,EAAE;QACd,GAAG,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,iCAAiC,CAAC,uCAAuC,CAC1E,CAAC;KACH;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,KAAK,gEAA0B,QAAgB;IAK7C,OAAO,uBAAA,IAAI,4FAAe,MAAnB,IAAI,EAAgB,KAAK,IAAI,EAAE;QACpC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAEhC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,cAAc,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,UAAU,CAAC,CAAC;SAC/D;QACD,sHAAsH;QACtH,yEAAyE;QACzE,+DAA+D;QAC/D,MAAM,kBAAkB,GAAG,MAAM,uBAAA,IAAI,oDAAgB,CAAC,OAAO,CAC3D,QAAQ,EACR,cAAc,CACf,CAAC;QAEF,MAAM,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,GAC5D,uBAAA,IAAI,6FAAgB,MAApB,IAAI,EAAiB,kBAAkB,CAAC,CAAC;QAE3C,oDAAoD;QACpD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,cAAc,GAAG,cAAc,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,4EACH,8BAGE;IAKF,IAAI;QACF,MAAM,OAAO,GAAG,MAAM,8BAA8B,EAAE,CAAC;QACvD,MAAM,iBAAiB,GAAG;YACxB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC;SAC7C,CAAC;QAEF,uBAAA,IAAI,0GAA6B,MAAjC,IAAI,EAA8B,iBAAiB,CAAC,CAAC;QAErD,OAAO,OAAO,CAAC;KAChB;IAAC,OAAO,KAAK,EAAE;QACd,GAAG,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC;KACb;AACH,CAAC,iIAE4B,uBAA8C;IACzE,qEAAqE;IACrE,wBAAwB;IACxB,MAAM,uBAAuB,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CACnE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,uBAAuB,CAAC,EAAE,CACrD,CAAC;IAEF,IAAI,CAAC,uBAAuB,EAAE;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,qBAAqB,GAAG;gBAC5B,GAAG,KAAK,CAAC,qBAAqB;gBAC9B,uBAAuB;aACxB,CAAC;QACJ,CAAC,CAAC,CAAC;KACJ;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,mEAA6B,EAChC,QAAQ,EACR,qBAAqB,EACrB,mBAAmB,GAKpB;IACC,uBAAA,IAAI,wGAA2B,MAA/B,IAAI,EAA4B,IAAI,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,GAAG,uBAAA,IAAI,+FAAkB,MAAtB,IAAI,EACnD,qBAAqB,EACrB,mBAAmB,CACpB,CAAC;IAEF,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC;QACzC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc;QACrC,kBAAkB;QAClB,gBAAgB;KACjB,CAAC,CAAC;IAEH,MAAM,uBAAA,IAAI,0FAAa,MAAjB,IAAI,EAAc;QACtB,QAAQ;QACR,mBAAmB;KACpB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,oDAAc,EACjB,QAAQ,EACR,mBAAmB,GAIpB;IACC,MAAM,uBAAA,IAAI,4FAAe,MAAnB,IAAI,EAAgB,KAAK,IAAI,EAAE;QACnC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAEhC,MAAM,YAAY,GAA+C,EAAE,CAAC;QAEpE,sHAAsH;QACtH,yEAAyE;QACzE,+DAA+D;QAC/D,YAAY,CAAC,KAAK,GAAG,MAAM,uBAAA,IAAI,oDAAgB,CAAC,OAAO,CACrD,QAAQ,EACR,mBAAmB,CACpB,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,sDACH,QAA2C;IAE3C,OAAO,MAAM,QAAQ,CAAC,uBAAA,IAAI,yDAAqB,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC,2GAUC,MAAkB,EAClB,WAAoB;IAKpB,MAAM,gBAAgB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,CAAC;QAC3C,EAAE,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,EAAE,EAAE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO;QACL,kBAAkB,EAAE,gBAAgB;QACpC,gBAAgB,EAAE,qBAAqB;KACxC,CAAC;AACJ,CAAC,uGASe,IAAa;IAK3B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,gBAAgB,CAAC,CAAC;KACrE;IAED,IAAI,eAAwB,CAAC;IAC7B,IAAI;QACF,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;KACpC;IAAC,MAAM;QACN,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,gBAAgB,CAAC,CAAC;KACrE;IAED,uBAAA,IAAI,qGAAwB,MAA5B,IAAI,EAAyB,eAAe,CAAC,CAAC;IAE9C,MAAM,qBAAqB,GAAG,aAAa,CACzC,eAAe,CAAC,kBAAkB,CACnC,CAAC;IACF,MAAM,sBAAsB,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAC5E,MAAM,mBAAmB,GAAG;QAC1B,EAAE,EAAE,MAAM,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACrC,EAAE,EAAE,aAAa,CAAC,sBAAsB,CAAC,EAAE,CAAC;KAC7C,CAAC;IAEF,OAAO;QACL,cAAc,EAAE,eAAe,CAAC,UAAU;QAC1C,kBAAkB,EAAE,qBAAqB;QACzC,gBAAgB,EAAE,mBAAmB;KACtC,CAAC;AACJ,CAAC,6HAeC,KAAc;IAEd,IACE,CAAC,KAAK;QACN,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,CAAC,kBAAkB,IAAI,KAAK,CAAC;QAC9B,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ;QAC1C,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC;QACpB,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAChC;QACA,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,mBAAmB,CAAC,CAAC;KACxE;IAED,IACE,CAAC,CAAC,gBAAgB,IAAI,KAAK,CAAC;QAC5B,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ;QACxC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;QACpC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,iEAAiE;MACjG;QACA,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,qBAAqB,CAAC,CAAC;KAC1E;AACH,CAAC,uHAQuB,KAAc;IACpC,6EAA6E;IAC7E,IACE,CAAC,KAAK,IAAI,uBAAuB;QACjC,OAAO,KAAK,KAAK,QAAQ,IAAI,yBAAyB;QACtD,CAAC,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,4BAA4B;QACxD,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,8BAA8B;QACtE,CAAC,CAAC,oBAAoB,IAAI,KAAK,CAAC,IAAI,oCAAoC;QACxE,OAAO,KAAK,CAAC,kBAAkB,KAAK,QAAQ,IAAI,qCAAqC;QACrF,CAAC,CAAC,kBAAkB,IAAI,KAAK,CAAC,IAAI,kCAAkC;QACpE,OAAO,KAAK,CAAC,gBAAgB,KAAK,QAAQ,CAAC,mCAAmC;MAC9E;QACA,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,cAAc,CAAC,CAAC;KACnE;AACH,CAAC;AAGH;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,QAAiB;IAC9C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;QAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,iBAAiB,CAAC,CAAC;KACtE;IAED,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,oBAAoB,CAAC,CAAC;KACzE;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,QAAQ,CACrB,KAAY,EACZ,QAA2C;IAE3C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IAE1C,IAAI;QACF,OAAO,MAAM,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;KACxC;YAAS;QACR,WAAW,EAAE,CAAC;KACf;AACH,CAAC","sourcesContent":["import { keccak256AndHexify } from '@metamask/auth-network-utils';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { encrypt, decrypt } from '@metamask/browser-passworder';\nimport type {\n KeyPair,\n NodeAuthTokens,\n SEC1EncodedPublicKey,\n} from '@metamask/toprf-secure-backup';\nimport { ToprfSecureBackup } from '@metamask/toprf-secure-backup';\nimport {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n remove0x,\n bigIntToHex,\n} from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n type AuthConnection,\n controllerName,\n SeedlessOnboardingControllerError,\n Web3AuthNetwork,\n} from './constants';\nimport { RecoveryError } from './errors';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { SeedPhraseMetadata } from './SeedPhraseMetadata';\nimport type {\n VaultEncryptor,\n MutuallyExclusiveCallback,\n SeedlessOnboardingControllerMessenger,\n SeedlessOnboardingControllerOptions,\n SeedlessOnboardingControllerState,\n VaultData,\n AuthenticatedUserDetails,\n SocialBackupsMetadata,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\n/**\n * Get the default state for the Seedless Onboarding Controller.\n *\n * @returns The default state for the Seedless Onboarding Controller.\n */\nexport function getDefaultSeedlessOnboardingControllerState(): SeedlessOnboardingControllerState {\n return {\n socialBackupsMetadata: [],\n };\n}\n\n/**\n * Seedless Onboarding Controller State Metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst seedlessOnboardingMetadata: StateMetadata<SeedlessOnboardingControllerState> =\n {\n vault: {\n persist: true,\n anonymous: false,\n },\n socialBackupsMetadata: {\n persist: true,\n anonymous: true,\n },\n nodeAuthTokens: {\n persist: false,\n anonymous: true,\n },\n authConnection: {\n persist: true,\n anonymous: true,\n },\n authConnectionId: {\n persist: true,\n anonymous: true,\n },\n groupedAuthConnectionId: {\n persist: true,\n anonymous: true,\n },\n userId: {\n persist: true,\n anonymous: true,\n },\n socialLoginEmail: {\n persist: true,\n anonymous: true,\n },\n };\n\nexport class SeedlessOnboardingController extends BaseController<\n typeof controllerName,\n SeedlessOnboardingControllerState,\n SeedlessOnboardingControllerMessenger\n> {\n readonly #vaultEncryptor: VaultEncryptor;\n\n readonly #vaultOperationMutex = new Mutex();\n\n readonly toprfClient: ToprfSecureBackup;\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.network - The network to be used for the Seedless Onboarding flow.\n */\n constructor({\n messenger,\n state,\n encryptor = { encrypt, decrypt }, // default to `encrypt` and `decrypt` from `@metamask/browser-passworder`\n network = Web3AuthNetwork.Mainnet,\n }: SeedlessOnboardingControllerOptions) {\n super({\n name: controllerName,\n metadata: seedlessOnboardingMetadata,\n state: {\n ...getDefaultSeedlessOnboardingControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#vaultEncryptor = encryptor;\n this.toprfClient = new ToprfSecureBackup({\n network,\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 * You can pass this to use aggregate multiple OAuth connections. Useful when you want user to have same account while using different OAuth connections.\n * @returns A promise that resolves to the authentication result.\n */\n async authenticate(params: {\n idTokens: string[];\n authConnection: AuthConnection;\n authConnectionId: string;\n userId: string;\n groupedAuthConnectionId?: string;\n socialLoginEmail?: string;\n }) {\n try {\n const {\n idTokens,\n authConnectionId,\n groupedAuthConnectionId,\n userId,\n authConnection,\n socialLoginEmail,\n } = params;\n const hashedIdTokenHexes = idTokens.map((idToken) => {\n return remove0x(keccak256AndHexify(stringToBytes(idToken)));\n });\n const authenticationResult = await this.toprfClient.authenticate({\n authConnectionId: groupedAuthConnectionId || authConnectionId,\n userId,\n idTokens: hashedIdTokenHexes,\n groupedAuthConnectionParams: {\n authConnectionId,\n idTokens,\n },\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 });\n return authenticationResult;\n } catch (error) {\n log('Error authenticating user', error);\n throw new Error(SeedlessOnboardingControllerError.AuthenticationError);\n }\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 seed phrase to backup\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 // 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 // locally evaluate the encryption key from the password\n const { encKey, authKeyPair, oprfKey } = this.toprfClient.createLocalKey({\n password,\n });\n\n // encrypt and store the seed phrase backup\n await this.#encryptAndStoreSeedPhraseBackup({\n keyringId,\n seedPhrase,\n encKey,\n authKeyPair,\n });\n\n // store/persist the encryption key shares\n // We store the seed phrase 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 rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n /**\n * Fetches all encrypted seed phrases and metadata for user's account from the metadata store.\n *\n * Decrypts the seed phrases and returns the decrypted seed phrases using the recovered encryption key from the password.\n *\n * @param password - The password used to create new wallet and seedphrase\n * @returns A promise that resolves to the seed phrase metadata.\n */\n async fetchAllSeedPhrases(password: string): Promise<Uint8Array[]> {\n // assert that the user is authenticated before fetching the seed phrases\n this.#assertIsAuthenticatedUser(this.state);\n\n const { encKey, authKeyPair } = await this.#recoverEncKey(password);\n\n try {\n const secretData = await this.toprfClient.fetchAllSecretDataItems({\n decKey: encKey,\n authKeyPair,\n });\n\n if (secretData?.length > 0) {\n await this.#createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey: encKey,\n rawToprfAuthKeyPair: authKeyPair,\n });\n }\n\n return SeedPhraseMetadata.parseSeedPhraseFromMetadataStore(secretData);\n } catch (error) {\n log('Error fetching seed phrase metadata', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToFetchSeedPhraseMetadata,\n );\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 */\n async changePassword(newPassword: string, oldPassword: string) {\n // verify the old password of the encrypted vault\n await this.#unlockVaultWithPassword(oldPassword);\n\n try {\n // update the encryption key with new password and update the Metadata Store\n const { encKey: newEncKey, authKeyPair: newAuthKeyPair } =\n await this.#changeEncryptionKey(newPassword, oldPassword);\n\n // update and encrypt the vault with new password\n await this.#createNewVaultWithAuthData({\n password: newPassword,\n rawToprfEncryptionKey: newEncKey,\n rawToprfAuthKeyPair: newAuthKeyPair,\n });\n } catch (error) {\n log('Error changing password', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToChangePassword);\n }\n }\n\n /**\n * Update the backup metadata state for the given seed phrase.\n *\n * @param keyringId - The keyring id of the backup seed phrase.\n * @param seedPhrase - The seed phrase to update the backup metadata for.\n */\n updateBackupMetadataState(keyringId: string, seedPhrase: Uint8Array) {\n const newBackupMetadata = {\n id: keyringId,\n hash: keccak256AndHexify(seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n }\n\n /**\n * Get the hash of the seed phrase backup for the given seed phrase, from the state.\n *\n * If the given seed phrase is not backed up and not found in the state, it will return `undefined`.\n *\n * @param seedPhrase - The seed phrase to get the hash of.\n * @returns A promise that resolves to the hash of the seed phrase backup.\n */\n getSeedPhraseBackupHash(\n seedPhrase: Uint8Array,\n ): SocialBackupsMetadata | undefined {\n const seedPhraseHash = keccak256AndHexify(seedPhrase);\n return this.state.socialBackupsMetadata.find(\n (backup) => backup.hash === seedPhraseHash,\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(oprfKey: bigint, authPubKey: SEC1EncodedPublicKey) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n await this.toprfClient.persistLocalKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n userId: this.state.userId,\n oprfKey,\n authPubKey,\n });\n } catch (error) {\n log('Error persisting local encryption key', error);\n throw new Error(SeedlessOnboardingControllerError.FailedToPersistOprfKey);\n }\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(password: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n try {\n const recoverEncKeyResult = await this.toprfClient.recoverEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n password,\n authConnectionId,\n userId: this.state.userId,\n });\n return recoverEncKeyResult;\n } catch (error) {\n throw RecoveryError.getInstance(error);\n }\n }\n\n /**\n * Update the encryption key with new password and update the Metadata Store with new encryption key.\n *\n * @param newPassword - The new password to update.\n * @param oldPassword - The old password to verify.\n * @returns A promise that resolves to new encryption key and authentication key pair.\n */\n async #changeEncryptionKey(newPassword: string, oldPassword: string) {\n this.#assertIsAuthenticatedUser(this.state);\n const authConnectionId =\n this.state.groupedAuthConnectionId || this.state.authConnectionId;\n\n const {\n encKey,\n authKeyPair,\n keyShareIndex: newKeyShareIndex,\n } = await this.#recoverEncKey(oldPassword);\n\n return await this.toprfClient.changeEncKey({\n nodeAuthTokens: this.state.nodeAuthTokens,\n authConnectionId,\n userId: this.state.userId,\n oldEncKey: encKey,\n oldAuthKeyPair: authKeyPair,\n newKeyShareIndex,\n oldPassword,\n newPassword,\n });\n }\n\n /**\n * Encrypt and store the seed phrase backup in the metadata store.\n *\n * @param params - The parameters for encrypting and storing the seed phrase backup.\n * @param params.keyringId - The keyring id of the backup seed phrase.\n * @param params.seedPhrase - The seed phrase to store.\n * @param params.encKey - The encryption key to store.\n * @param params.authKeyPair - The authentication key pair to store.\n *\n * @returns A promise that resolves to the success of the operation.\n */\n async #encryptAndStoreSeedPhraseBackup(params: {\n keyringId: string;\n seedPhrase: Uint8Array;\n encKey: Uint8Array;\n authKeyPair: KeyPair;\n }): Promise<void> {\n try {\n const { keyringId, seedPhrase, encKey, authKeyPair } = params;\n\n const seedPhraseMetadata = new SeedPhraseMetadata(seedPhrase);\n const secretData = seedPhraseMetadata.toBytes();\n await this.#withPersistedSeedPhraseBackupsState(async () => {\n await this.toprfClient.addSecretDataItem({\n encKey,\n secretData,\n authKeyPair,\n });\n return {\n id: keyringId,\n seedPhrase,\n };\n });\n } catch (error) {\n log('Error encrypting and storing seed phrase backup', error);\n throw new Error(\n SeedlessOnboardingControllerError.FailedToEncryptAndStoreSeedPhraseBackup,\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 password - The password to decrypt the vault.\n * @returns A promise that resolves to an object containing:\n * - nodeAuthTokens: Authentication tokens to communicate with the TOPRF service\n * - toprfEncryptionKey: The decrypted TOPRF encryption key\n * - toprfAuthKeyPair: The decrypted TOPRF authentication key pair\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 #unlockVaultWithPassword(password: string): Promise<{\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n }> {\n return this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const encryptedVault = this.state.vault;\n if (!encryptedVault) {\n throw new Error(SeedlessOnboardingControllerError.VaultError);\n }\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 decryptedVaultData = await this.#vaultEncryptor.decrypt(\n password,\n encryptedVault,\n );\n\n const { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair } =\n this.#parseVaultData(decryptedVaultData);\n\n // update the state with the restored nodeAuthTokens\n this.update((state) => {\n state.nodeAuthTokens = nodeAuthTokens;\n });\n\n return { nodeAuthTokens, toprfEncryptionKey, toprfAuthKeyPair };\n });\n }\n\n /**\n * Executes a callback function that creates or restores seed phrases and persists their hashes in the controller state.\n *\n * This method:\n * 1. Executes the provided callback to create/restore seed phrases\n * 2. Generates keccak256 hashes of the seed phrases\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 seed phrases to ensure their hashes are properly tracked.\n *\n * @param createSeedPhraseBackupCallback - function that returns either a single seed phrase\n * or an array of seed phrases as Uint8Array(s)\n * @returns The original seed phrase(s) returned by the callback\n * @throws Rethrows any errors from the callback with additional logging\n */\n async #withPersistedSeedPhraseBackupsState(\n createSeedPhraseBackupCallback: () => Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }>,\n ): Promise<{\n id: string;\n seedPhrase: Uint8Array;\n }> {\n try {\n const backUps = await createSeedPhraseBackupCallback();\n const newBackupMetadata = {\n id: backUps.id,\n hash: keccak256AndHexify(backUps.seedPhrase),\n };\n\n this.#updateSocialBackupsMetadata(newBackupMetadata);\n\n return backUps;\n } catch (error) {\n log('Error persisting seed phrase backups', error);\n throw error;\n }\n }\n\n #updateSocialBackupsMetadata(newSocialBackupMetadata: SocialBackupsMetadata) {\n // filter out the backed up metadata that already exists in the state\n // to prevent duplicates\n const existingBackupsMetadata = this.state.socialBackupsMetadata.find(\n (backup) => backup.id === newSocialBackupMetadata.id,\n );\n\n if (!existingBackupsMetadata) {\n this.update((state) => {\n state.socialBackupsMetadata = [\n ...state.socialBackupsMetadata,\n newSocialBackupMetadata,\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.rawToprfAuthKeyPair - The authentication key pair to encrypt the vault.\n */\n async #createNewVaultWithAuthData({\n password,\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n }: {\n password: string;\n rawToprfEncryptionKey: Uint8Array;\n rawToprfAuthKeyPair: KeyPair;\n }): Promise<void> {\n this.#assertIsAuthenticatedUser(this.state);\n\n const { toprfEncryptionKey, toprfAuthKeyPair } = this.#serializeKeyData(\n rawToprfEncryptionKey,\n rawToprfAuthKeyPair,\n );\n\n const serializedVaultData = JSON.stringify({\n authTokens: this.state.nodeAuthTokens,\n toprfEncryptionKey,\n toprfAuthKeyPair,\n });\n\n await this.#updateVault({\n password,\n serializedVaultData,\n });\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 password to encrypt the vault.\n * @param params.serializedVaultData - The serialized authentication data to update the vault with.\n * @returns A promise that resolves to the updated vault.\n */\n async #updateVault({\n password,\n serializedVaultData,\n }: {\n password: string;\n serializedVaultData: string;\n }): Promise<void> {\n await this.#withVaultLock(async () => {\n assertIsValidPassword(password);\n\n const updatedState: Partial<SeedlessOnboardingControllerState> = {};\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 updatedState.vault = await this.#vaultEncryptor.encrypt(\n password,\n serializedVaultData,\n );\n\n this.update((state) => {\n state.vault = updatedState.vault;\n });\n });\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 /**\n * Serialize the encryption key and authentication key pair.\n *\n * @param encKey - The encryption key to serialize.\n * @param authKeyPair - The authentication key pair to serialize.\n * @returns The serialized encryption key and authentication key pair.\n */\n #serializeKeyData(\n encKey: Uint8Array,\n authKeyPair: KeyPair,\n ): {\n toprfEncryptionKey: string;\n toprfAuthKeyPair: string;\n } {\n const b64EncodedEncKey = bytesToBase64(encKey);\n const b64EncodedAuthKeyPair = JSON.stringify({\n sk: bigIntToHex(authKeyPair.sk), // Convert BigInt to hex string\n pk: bytesToBase64(authKeyPair.pk),\n });\n\n return {\n toprfEncryptionKey: b64EncodedEncKey,\n toprfAuthKeyPair: b64EncodedAuthKeyPair,\n };\n }\n\n /**\n * Parse and deserialize the authentication data from the vault.\n *\n * @param data - The decrypted vault data.\n * @returns The parsed authentication data.\n * @throws If the vault data is not valid.\n */\n #parseVaultData(data: unknown): {\n nodeAuthTokens: NodeAuthTokens;\n toprfEncryptionKey: Uint8Array;\n toprfAuthKeyPair: KeyPair;\n } {\n if (typeof data !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n let parsedVaultData: unknown;\n try {\n parsedVaultData = JSON.parse(data);\n } catch {\n throw new Error(SeedlessOnboardingControllerError.InvalidVaultData);\n }\n\n this.#assertIsValidVaultData(parsedVaultData);\n\n const rawToprfEncryptionKey = base64ToBytes(\n parsedVaultData.toprfEncryptionKey,\n );\n const parsedToprfAuthKeyPair = JSON.parse(parsedVaultData.toprfAuthKeyPair);\n const rawToprfAuthKeyPair = {\n sk: BigInt(parsedToprfAuthKeyPair.sk),\n pk: base64ToBytes(parsedToprfAuthKeyPair.pk),\n };\n\n return {\n nodeAuthTokens: parsedVaultData.authTokens,\n toprfEncryptionKey: rawToprfEncryptionKey,\n toprfAuthKeyPair: rawToprfAuthKeyPair,\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 if (\n !value ||\n typeof value !== 'object' ||\n !('authConnectionId' in value) ||\n typeof value.authConnectionId !== 'string' ||\n !('userId' in value) ||\n typeof value.userId !== 'string'\n ) {\n throw new Error(SeedlessOnboardingControllerError.MissingAuthUserInfo);\n }\n\n if (\n !('nodeAuthTokens' in value) ||\n typeof value.nodeAuthTokens !== 'object' ||\n !Array.isArray(value.nodeAuthTokens) ||\n value.nodeAuthTokens.length < 3 // At least 3 auth tokens are required for Threshold OPRF service\n ) {\n throw new Error(SeedlessOnboardingControllerError.InsufficientAuthToken);\n }\n }\n\n /**\n * Check if the provided value is a valid vault data.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid vault data.\n */\n #assertIsValidVaultData(value: unknown): asserts value is VaultData {\n // value is not valid vault data if any of the following conditions are true:\n if (\n !value || // value is not defined\n typeof value !== 'object' || // value is not an object\n !('authTokens' in value) || // authTokens is not defined\n typeof value.authTokens !== 'object' || // authTokens is not an object\n !('toprfEncryptionKey' in value) || // toprfEncryptionKey is not defined\n typeof value.toprfEncryptionKey !== 'string' || // toprfEncryptionKey is not a string\n !('toprfAuthKeyPair' in value) || // toprfAuthKeyPair is not defined\n typeof value.toprfAuthKeyPair !== 'string' // toprfAuthKeyPair is not a string\n ) {\n throw new Error(SeedlessOnboardingControllerError.VaultDataError);\n }\n }\n}\n\n/**\n * Assert that the provided password is a valid non-empty string.\n *\n * @param password - The password to check.\n * @throws If the password is not a valid string.\n */\nfunction assertIsValidPassword(password: unknown): asserts password is string {\n if (typeof password !== 'string') {\n throw new Error(SeedlessOnboardingControllerError.WrongPasswordType);\n }\n\n if (!password || !password.length) {\n throw new Error(SeedlessOnboardingControllerError.InvalidEmptyPassword);\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/errors.cjs CHANGED
@@ -12,9 +12,9 @@ const constants_1 = require("./constants.cjs");
12
12
  */
13
13
  function getErrorMessageFromTOPRFErrorCode(errorCode, defaultMessage) {
14
14
  switch (errorCode) {
15
- case toprf_secure_backup_1.TORPFErrorCode.RateLimitExceeded:
15
+ case toprf_secure_backup_1.TOPRFErrorCode.RateLimitExceeded:
16
16
  return constants_1.SeedlessOnboardingControllerError.TooManyLoginAttempts;
17
- case toprf_secure_backup_1.TORPFErrorCode.CouldNotDeriveEncryptionKey:
17
+ case toprf_secure_backup_1.TOPRFErrorCode.CouldNotDeriveEncryptionKey:
18
18
  return constants_1.SeedlessOnboardingControllerError.IncorrectPassword;
19
19
  default:
20
20
  return defaultMessage;
@@ -54,7 +54,7 @@ class RecoveryError extends Error {
54
54
  */
55
55
  static getRateLimitErrorData(error) {
56
56
  if (error.meta && // error metadata must be present
57
- error.code === toprf_secure_backup_1.TORPFErrorCode.RateLimitExceeded &&
57
+ error.code === toprf_secure_backup_1.TOPRFErrorCode.RateLimitExceeded &&
58
58
  typeof error.meta.rateLimitDetails === 'object' &&
59
59
  error.meta.rateLimitDetails !== null &&
60
60
  'remainingTime' in error.meta.rateLimitDetails &&
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,uEAIuC;AAEvC,+CAAgE;AAEhE;;;;;;GAMG;AACH,SAAS,iCAAiC,CACxC,SAAyB,EACzB,cAAsB;IAEtB,QAAQ,SAAS,EAAE;QACjB,KAAK,oCAAc,CAAC,iBAAiB;YACnC,OAAO,6CAAiC,CAAC,oBAAoB,CAAC;QAChE,KAAK,oCAAc,CAAC,2BAA2B;YAC7C,OAAO,6CAAiC,CAAC,iBAAiB,CAAC;QAC7D;YACE,OAAO,cAAc,CAAC;KACzB;AACH,CAAC;AAED;;;GAGG;AACH,MAAa,aAAc,SAAQ,KAAK;IAGtC,YAAY,OAAe,EAAE,IAAyB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,8CAA8C,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,KAAc;QAC/B,IAAI,KAAK,YAAY,gCAAU,EAAE;YAC/B,MAAM,kBAAkB,GAAG,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,YAAY,GAAG,iCAAiC,CACpD,KAAK,CAAC,IAAI,EACV,6CAAiC,CAAC,gBAAgB,CACnD,CAAC;YACF,OAAO,IAAI,aAAa,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;SAC5D;QACD,OAAO,IAAI,aAAa,CACtB,6CAAiC,CAAC,gBAAgB,CACnD,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,qBAAqB,CAC1B,KAAiB;QAEjB,IACE,KAAK,CAAC,IAAI,IAAI,iCAAiC;YAC/C,KAAK,CAAC,IAAI,KAAK,oCAAc,CAAC,iBAAiB;YAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,QAAQ;YAC/C,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,IAAI;YACpC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,KAAK,QAAQ;YAC7D,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YACxC,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,QAAQ,EACvD;YACA,OAAO;gBACL,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa;gBACxD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO;aAC7C,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAzDD,sCAyDC","sourcesContent":["import {\n type RateLimitErrorData,\n TOPRFError,\n TORPFErrorCode,\n} from '@metamask/toprf-secure-backup';\n\nimport { SeedlessOnboardingControllerError } from './constants';\n\n/**\n * Get the error message from the TOPRF error code.\n *\n * @param errorCode - The TOPRF error code.\n * @param defaultMessage - The default error message if the error code is not found.\n * @returns The error message.\n */\nfunction getErrorMessageFromTOPRFErrorCode(\n errorCode: TORPFErrorCode,\n defaultMessage: string,\n): string {\n switch (errorCode) {\n case TORPFErrorCode.RateLimitExceeded:\n return SeedlessOnboardingControllerError.TooManyLoginAttempts;\n case TORPFErrorCode.CouldNotDeriveEncryptionKey:\n return SeedlessOnboardingControllerError.IncorrectPassword;\n default:\n return defaultMessage;\n }\n}\n\n/**\n * The RecoveryError class is used to handle errors that occur during the recover encryption key process from the passwrord.\n * It extends the Error class and includes a data property that can be used to store additional information.\n */\nexport class RecoveryError extends Error {\n data: RateLimitErrorData | undefined;\n\n constructor(message: string, data?: RateLimitErrorData) {\n super(message);\n this.data = data;\n this.name = 'SeedlessOnboardingController - RecoveryError';\n }\n\n /**\n * Get an instance of the RecoveryError class.\n *\n * @param error - The error to get the instance of.\n * @returns The instance of the RecoveryError class.\n */\n static getInstance(error: unknown): RecoveryError {\n if (error instanceof TOPRFError) {\n const rateLimitErrorData = RecoveryError.getRateLimitErrorData(error);\n const errorMessage = getErrorMessageFromTOPRFErrorCode(\n error.code,\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n return new RecoveryError(errorMessage, rateLimitErrorData);\n }\n return new RecoveryError(\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n }\n\n /**\n * Check if the provided error is a rate limit error triggered by too many login attempts.\n *\n * Return a new TooManyLoginAttemptsError if the error is a rate limit error, otherwise undefined.\n *\n * @param error - The error to check.\n * @returns The rate limit error if the error is a rate limit error, otherwise undefined.\n */\n static getRateLimitErrorData(\n error: TOPRFError,\n ): RateLimitErrorData | undefined {\n if (\n error.meta && // error metadata must be present\n error.code === TORPFErrorCode.RateLimitExceeded &&\n typeof error.meta.rateLimitDetails === 'object' &&\n error.meta.rateLimitDetails !== null &&\n 'remainingTime' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.remainingTime === 'number' &&\n 'message' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.message === 'string'\n ) {\n return {\n remainingTime: error.meta.rateLimitDetails.remainingTime,\n message: error.meta.rateLimitDetails.message,\n };\n }\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"errors.cjs","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,uEAIuC;AAEvC,+CAAgE;AAEhE;;;;;;GAMG;AACH,SAAS,iCAAiC,CACxC,SAAyB,EACzB,cAAsB;IAEtB,QAAQ,SAAS,EAAE;QACjB,KAAK,oCAAc,CAAC,iBAAiB;YACnC,OAAO,6CAAiC,CAAC,oBAAoB,CAAC;QAChE,KAAK,oCAAc,CAAC,2BAA2B;YAC7C,OAAO,6CAAiC,CAAC,iBAAiB,CAAC;QAC7D;YACE,OAAO,cAAc,CAAC;KACzB;AACH,CAAC;AAED;;;GAGG;AACH,MAAa,aAAc,SAAQ,KAAK;IAGtC,YAAY,OAAe,EAAE,IAAyB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,8CAA8C,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,KAAc;QAC/B,IAAI,KAAK,YAAY,gCAAU,EAAE;YAC/B,MAAM,kBAAkB,GAAG,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,YAAY,GAAG,iCAAiC,CACpD,KAAK,CAAC,IAAI,EACV,6CAAiC,CAAC,gBAAgB,CACnD,CAAC;YACF,OAAO,IAAI,aAAa,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;SAC5D;QACD,OAAO,IAAI,aAAa,CACtB,6CAAiC,CAAC,gBAAgB,CACnD,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,qBAAqB,CAC1B,KAAiB;QAEjB,IACE,KAAK,CAAC,IAAI,IAAI,iCAAiC;YAC/C,KAAK,CAAC,IAAI,KAAK,oCAAc,CAAC,iBAAiB;YAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,QAAQ;YAC/C,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,IAAI;YACpC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,KAAK,QAAQ;YAC7D,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YACxC,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,QAAQ,EACvD;YACA,OAAO;gBACL,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa;gBACxD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO;aAC7C,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAzDD,sCAyDC","sourcesContent":["import {\n type RateLimitErrorData,\n TOPRFError,\n TOPRFErrorCode,\n} from '@metamask/toprf-secure-backup';\n\nimport { SeedlessOnboardingControllerError } from './constants';\n\n/**\n * Get the error message from the TOPRF error code.\n *\n * @param errorCode - The TOPRF error code.\n * @param defaultMessage - The default error message if the error code is not found.\n * @returns The error message.\n */\nfunction getErrorMessageFromTOPRFErrorCode(\n errorCode: TOPRFErrorCode,\n defaultMessage: string,\n): string {\n switch (errorCode) {\n case TOPRFErrorCode.RateLimitExceeded:\n return SeedlessOnboardingControllerError.TooManyLoginAttempts;\n case TOPRFErrorCode.CouldNotDeriveEncryptionKey:\n return SeedlessOnboardingControllerError.IncorrectPassword;\n default:\n return defaultMessage;\n }\n}\n\n/**\n * The RecoveryError class is used to handle errors that occur during the recover encryption key process from the passwrord.\n * It extends the Error class and includes a data property that can be used to store additional information.\n */\nexport class RecoveryError extends Error {\n data: RateLimitErrorData | undefined;\n\n constructor(message: string, data?: RateLimitErrorData) {\n super(message);\n this.data = data;\n this.name = 'SeedlessOnboardingController - RecoveryError';\n }\n\n /**\n * Get an instance of the RecoveryError class.\n *\n * @param error - The error to get the instance of.\n * @returns The instance of the RecoveryError class.\n */\n static getInstance(error: unknown): RecoveryError {\n if (error instanceof TOPRFError) {\n const rateLimitErrorData = RecoveryError.getRateLimitErrorData(error);\n const errorMessage = getErrorMessageFromTOPRFErrorCode(\n error.code,\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n return new RecoveryError(errorMessage, rateLimitErrorData);\n }\n return new RecoveryError(\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n }\n\n /**\n * Check if the provided error is a rate limit error triggered by too many login attempts.\n *\n * Return a new TooManyLoginAttemptsError if the error is a rate limit error, otherwise undefined.\n *\n * @param error - The error to check.\n * @returns The rate limit error if the error is a rate limit error, otherwise undefined.\n */\n static getRateLimitErrorData(\n error: TOPRFError,\n ): RateLimitErrorData | undefined {\n if (\n error.meta && // error metadata must be present\n error.code === TOPRFErrorCode.RateLimitExceeded &&\n typeof error.meta.rateLimitDetails === 'object' &&\n error.meta.rateLimitDetails !== null &&\n 'remainingTime' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.remainingTime === 'number' &&\n 'message' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.message === 'string'\n ) {\n return {\n remainingTime: error.meta.rateLimitDetails.remainingTime,\n message: error.meta.rateLimitDetails.message,\n };\n }\n return undefined;\n }\n}\n"]}
package/dist/errors.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { TOPRFError, TORPFErrorCode } from "@metamask/toprf-secure-backup";
1
+ import { TOPRFError, TOPRFErrorCode } from "@metamask/toprf-secure-backup";
2
2
  import { SeedlessOnboardingControllerError } from "./constants.mjs";
3
3
  /**
4
4
  * Get the error message from the TOPRF error code.
@@ -9,9 +9,9 @@ import { SeedlessOnboardingControllerError } from "./constants.mjs";
9
9
  */
10
10
  function getErrorMessageFromTOPRFErrorCode(errorCode, defaultMessage) {
11
11
  switch (errorCode) {
12
- case TORPFErrorCode.RateLimitExceeded:
12
+ case TOPRFErrorCode.RateLimitExceeded:
13
13
  return SeedlessOnboardingControllerError.TooManyLoginAttempts;
14
- case TORPFErrorCode.CouldNotDeriveEncryptionKey:
14
+ case TOPRFErrorCode.CouldNotDeriveEncryptionKey:
15
15
  return SeedlessOnboardingControllerError.IncorrectPassword;
16
16
  default:
17
17
  return defaultMessage;
@@ -51,7 +51,7 @@ export class RecoveryError extends Error {
51
51
  */
52
52
  static getRateLimitErrorData(error) {
53
53
  if (error.meta && // error metadata must be present
54
- error.code === TORPFErrorCode.RateLimitExceeded &&
54
+ error.code === TOPRFErrorCode.RateLimitExceeded &&
55
55
  typeof error.meta.rateLimitDetails === 'object' &&
56
56
  error.meta.rateLimitDetails !== null &&
57
57
  'remainingTime' in error.meta.rateLimitDetails &&
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EACV,cAAc,EACf,sCAAsC;AAEvC,OAAO,EAAE,iCAAiC,EAAE,wBAAoB;AAEhE;;;;;;GAMG;AACH,SAAS,iCAAiC,CACxC,SAAyB,EACzB,cAAsB;IAEtB,QAAQ,SAAS,EAAE;QACjB,KAAK,cAAc,CAAC,iBAAiB;YACnC,OAAO,iCAAiC,CAAC,oBAAoB,CAAC;QAChE,KAAK,cAAc,CAAC,2BAA2B;YAC7C,OAAO,iCAAiC,CAAC,iBAAiB,CAAC;QAC7D;YACE,OAAO,cAAc,CAAC;KACzB;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGtC,YAAY,OAAe,EAAE,IAAyB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,8CAA8C,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,KAAc;QAC/B,IAAI,KAAK,YAAY,UAAU,EAAE;YAC/B,MAAM,kBAAkB,GAAG,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,YAAY,GAAG,iCAAiC,CACpD,KAAK,CAAC,IAAI,EACV,iCAAiC,CAAC,gBAAgB,CACnD,CAAC;YACF,OAAO,IAAI,aAAa,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;SAC5D;QACD,OAAO,IAAI,aAAa,CACtB,iCAAiC,CAAC,gBAAgB,CACnD,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,qBAAqB,CAC1B,KAAiB;QAEjB,IACE,KAAK,CAAC,IAAI,IAAI,iCAAiC;YAC/C,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB;YAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,QAAQ;YAC/C,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,IAAI;YACpC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,KAAK,QAAQ;YAC7D,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YACxC,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,QAAQ,EACvD;YACA,OAAO;gBACL,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa;gBACxD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO;aAC7C,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF","sourcesContent":["import {\n type RateLimitErrorData,\n TOPRFError,\n TORPFErrorCode,\n} from '@metamask/toprf-secure-backup';\n\nimport { SeedlessOnboardingControllerError } from './constants';\n\n/**\n * Get the error message from the TOPRF error code.\n *\n * @param errorCode - The TOPRF error code.\n * @param defaultMessage - The default error message if the error code is not found.\n * @returns The error message.\n */\nfunction getErrorMessageFromTOPRFErrorCode(\n errorCode: TORPFErrorCode,\n defaultMessage: string,\n): string {\n switch (errorCode) {\n case TORPFErrorCode.RateLimitExceeded:\n return SeedlessOnboardingControllerError.TooManyLoginAttempts;\n case TORPFErrorCode.CouldNotDeriveEncryptionKey:\n return SeedlessOnboardingControllerError.IncorrectPassword;\n default:\n return defaultMessage;\n }\n}\n\n/**\n * The RecoveryError class is used to handle errors that occur during the recover encryption key process from the passwrord.\n * It extends the Error class and includes a data property that can be used to store additional information.\n */\nexport class RecoveryError extends Error {\n data: RateLimitErrorData | undefined;\n\n constructor(message: string, data?: RateLimitErrorData) {\n super(message);\n this.data = data;\n this.name = 'SeedlessOnboardingController - RecoveryError';\n }\n\n /**\n * Get an instance of the RecoveryError class.\n *\n * @param error - The error to get the instance of.\n * @returns The instance of the RecoveryError class.\n */\n static getInstance(error: unknown): RecoveryError {\n if (error instanceof TOPRFError) {\n const rateLimitErrorData = RecoveryError.getRateLimitErrorData(error);\n const errorMessage = getErrorMessageFromTOPRFErrorCode(\n error.code,\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n return new RecoveryError(errorMessage, rateLimitErrorData);\n }\n return new RecoveryError(\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n }\n\n /**\n * Check if the provided error is a rate limit error triggered by too many login attempts.\n *\n * Return a new TooManyLoginAttemptsError if the error is a rate limit error, otherwise undefined.\n *\n * @param error - The error to check.\n * @returns The rate limit error if the error is a rate limit error, otherwise undefined.\n */\n static getRateLimitErrorData(\n error: TOPRFError,\n ): RateLimitErrorData | undefined {\n if (\n error.meta && // error metadata must be present\n error.code === TORPFErrorCode.RateLimitExceeded &&\n typeof error.meta.rateLimitDetails === 'object' &&\n error.meta.rateLimitDetails !== null &&\n 'remainingTime' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.remainingTime === 'number' &&\n 'message' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.message === 'string'\n ) {\n return {\n remainingTime: error.meta.rateLimitDetails.remainingTime,\n message: error.meta.rateLimitDetails.message,\n };\n }\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"errors.mjs","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EACV,cAAc,EACf,sCAAsC;AAEvC,OAAO,EAAE,iCAAiC,EAAE,wBAAoB;AAEhE;;;;;;GAMG;AACH,SAAS,iCAAiC,CACxC,SAAyB,EACzB,cAAsB;IAEtB,QAAQ,SAAS,EAAE;QACjB,KAAK,cAAc,CAAC,iBAAiB;YACnC,OAAO,iCAAiC,CAAC,oBAAoB,CAAC;QAChE,KAAK,cAAc,CAAC,2BAA2B;YAC7C,OAAO,iCAAiC,CAAC,iBAAiB,CAAC;QAC7D;YACE,OAAO,cAAc,CAAC;KACzB;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGtC,YAAY,OAAe,EAAE,IAAyB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,8CAA8C,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,KAAc;QAC/B,IAAI,KAAK,YAAY,UAAU,EAAE;YAC/B,MAAM,kBAAkB,GAAG,aAAa,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,YAAY,GAAG,iCAAiC,CACpD,KAAK,CAAC,IAAI,EACV,iCAAiC,CAAC,gBAAgB,CACnD,CAAC;YACF,OAAO,IAAI,aAAa,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;SAC5D;QACD,OAAO,IAAI,aAAa,CACtB,iCAAiC,CAAC,gBAAgB,CACnD,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,qBAAqB,CAC1B,KAAiB;QAEjB,IACE,KAAK,CAAC,IAAI,IAAI,iCAAiC;YAC/C,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB;YAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,QAAQ;YAC/C,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,IAAI;YACpC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,KAAK,QAAQ;YAC7D,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YACxC,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,QAAQ,EACvD;YACA,OAAO;gBACL,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa;gBACxD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO;aAC7C,CAAC;SACH;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF","sourcesContent":["import {\n type RateLimitErrorData,\n TOPRFError,\n TOPRFErrorCode,\n} from '@metamask/toprf-secure-backup';\n\nimport { SeedlessOnboardingControllerError } from './constants';\n\n/**\n * Get the error message from the TOPRF error code.\n *\n * @param errorCode - The TOPRF error code.\n * @param defaultMessage - The default error message if the error code is not found.\n * @returns The error message.\n */\nfunction getErrorMessageFromTOPRFErrorCode(\n errorCode: TOPRFErrorCode,\n defaultMessage: string,\n): string {\n switch (errorCode) {\n case TOPRFErrorCode.RateLimitExceeded:\n return SeedlessOnboardingControllerError.TooManyLoginAttempts;\n case TOPRFErrorCode.CouldNotDeriveEncryptionKey:\n return SeedlessOnboardingControllerError.IncorrectPassword;\n default:\n return defaultMessage;\n }\n}\n\n/**\n * The RecoveryError class is used to handle errors that occur during the recover encryption key process from the passwrord.\n * It extends the Error class and includes a data property that can be used to store additional information.\n */\nexport class RecoveryError extends Error {\n data: RateLimitErrorData | undefined;\n\n constructor(message: string, data?: RateLimitErrorData) {\n super(message);\n this.data = data;\n this.name = 'SeedlessOnboardingController - RecoveryError';\n }\n\n /**\n * Get an instance of the RecoveryError class.\n *\n * @param error - The error to get the instance of.\n * @returns The instance of the RecoveryError class.\n */\n static getInstance(error: unknown): RecoveryError {\n if (error instanceof TOPRFError) {\n const rateLimitErrorData = RecoveryError.getRateLimitErrorData(error);\n const errorMessage = getErrorMessageFromTOPRFErrorCode(\n error.code,\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n return new RecoveryError(errorMessage, rateLimitErrorData);\n }\n return new RecoveryError(\n SeedlessOnboardingControllerError.LoginFailedError,\n );\n }\n\n /**\n * Check if the provided error is a rate limit error triggered by too many login attempts.\n *\n * Return a new TooManyLoginAttemptsError if the error is a rate limit error, otherwise undefined.\n *\n * @param error - The error to check.\n * @returns The rate limit error if the error is a rate limit error, otherwise undefined.\n */\n static getRateLimitErrorData(\n error: TOPRFError,\n ): RateLimitErrorData | undefined {\n if (\n error.meta && // error metadata must be present\n error.code === TOPRFErrorCode.RateLimitExceeded &&\n typeof error.meta.rateLimitDetails === 'object' &&\n error.meta.rateLimitDetails !== null &&\n 'remainingTime' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.remainingTime === 'number' &&\n 'message' in error.meta.rateLimitDetails &&\n typeof error.meta.rateLimitDetails.message === 'string'\n ) {\n return {\n remainingTime: error.meta.rateLimitDetails.remainingTime,\n message: error.meta.rateLimitDetails.message,\n };\n }\n return undefined;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/seedless-onboarding-controller",
3
- "version": "0.0.0-preview-7aa27646",
3
+ "version": "0.0.0-preview-971e1a64",
4
4
  "description": "Backup and rehydrate SRP(s) using social login and password",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -47,14 +47,16 @@
47
47
  "since-latest-release": "../../scripts/since-latest-release.sh"
48
48
  },
49
49
  "dependencies": {
50
- "@metamask/auth-network-utils": "./auth-network-utils.tgz",
51
- "@metamask/base-controller": "^8.0.0",
50
+ "@metamask/auth-network-utils": "^0.1.0",
51
+ "@metamask/base-controller": "^8.0.1",
52
52
  "@metamask/browser-passworder": "^4.3.0",
53
- "@metamask/toprf-secure-backup": "./toprf-secure-backup.tgz",
53
+ "@metamask/toprf-secure-backup": "^0.1.0",
54
54
  "@metamask/utils": "^11.2.0",
55
55
  "async-mutex": "^0.5.0"
56
56
  },
57
57
  "devDependencies": {
58
+ "@lavamoat/allow-scripts": "^3.0.4",
59
+ "@lavamoat/preinstall-always-fail": "^2.1.0",
58
60
  "@metamask/auto-changelog": "^3.4.4",
59
61
  "@noble/ciphers": "^0.5.2",
60
62
  "@noble/curves": "^1.2.0",
@@ -76,5 +78,11 @@
76
78
  "publishConfig": {
77
79
  "access": "public",
78
80
  "registry": "https://registry.npmjs.org/"
81
+ },
82
+ "lavamoat": {
83
+ "allowScripts": {
84
+ "@lavamoat/preinstall-always-fail": false,
85
+ "@metamask/toprf-secure-backup": true
86
+ }
79
87
  }
80
88
  }