@metamask-previews/seedless-onboarding-controller 2.0.1-preview-c10fdda1 → 2.0.1-preview-32f9004a

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