@idos-network/enclave 1.5.0 → 2.2.0

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/src/local.ts CHANGED
@@ -96,7 +96,7 @@ export class LocalEnclave<
96
96
  async reset(): Promise<void> {
97
97
  await super.reset();
98
98
  this.storedEncryptionProfile = undefined;
99
- this.store.reset();
99
+ await this.store.reset();
100
100
  }
101
101
 
102
102
  /** @override parent method to reconfigure the enclave */
@@ -266,26 +266,32 @@ export class LocalEnclave<
266
266
  * @see BaseProvider#getPrivateEncryptionProfile
267
267
  */
268
268
  async getPrivateEncryptionProfile(skipGuard = false): Promise<PrivateEncryptionProfile> {
269
- // In case there is a no key pair, which matches we don't need a new one.
270
- if (this.storedEncryptionProfile) {
271
- let canBeUsed = this.storedEncryptionProfile.userId === this.userId;
269
+ // Remember duration is a key-use check. A long-lived iframe keeps this profile
270
+ // in memory, so construction-time store expiry is not enough.
271
+ if (this.storedEncryptionProfile && (await this.store.hasRememberDurationElapsed())) {
272
+ await this.reset();
273
+ }
272
274
 
273
- if (canBeUsed && !skipGuard) {
274
- // When users matches, we also need to check
275
- // if origin is authorized to use the keys.
276
- canBeUsed = await this.guardKeys();
275
+ if (this.storedEncryptionProfile?.userId === this.userId) {
276
+ // A matching cached profile still needs origin authorization before key use.
277
+ // Denying it must keep the profile and the allowlist; only a different user resets.
278
+ if (!skipGuard && !(await this.guardKeys())) {
279
+ throw new Error("Origin is not authorized to use the keys");
277
280
  }
278
281
 
279
- if (canBeUsed) {
280
- return this.storedEncryptionProfile;
281
- }
282
+ return this.storedEncryptionProfile;
283
+ }
282
284
 
283
- // Something did not match, we need to create a new key pair
284
- // and reset the enclave.
285
+ if (this.storedEncryptionProfile) {
285
286
  await this.reset();
286
287
  }
287
288
 
288
- // The stored profile can't be used, or we have to create a new one.
289
+ if (this.options.encryptionPasswordStore === "mm") {
290
+ throw new Error(
291
+ "MM encryption profiles require an externally supplied encryption private key",
292
+ );
293
+ }
294
+
289
295
  let password: string | undefined;
290
296
  let encryptionPasswordStore: EncryptionPasswordStore | undefined;
291
297
 
@@ -310,7 +316,18 @@ export class LocalEnclave<
310
316
  throw new Error("Password or encryption password store is not found");
311
317
  }
312
318
 
313
- return this.createEncryptionProfileFromPassword(password, this.userId, encryptionPasswordStore);
319
+ const profile = await this.createEncryptionProfileFromPassword(
320
+ password,
321
+ this.userId,
322
+ encryptionPasswordStore,
323
+ );
324
+
325
+ // Same origin check as the cached path. Password or MPC success is not authorization.
326
+ if (!skipGuard && !(await this.guardKeys())) {
327
+ throw new Error("Origin is not authorized to use the keys");
328
+ }
329
+
330
+ return profile;
314
331
  }
315
332
 
316
333
  /** @see BaseProvider#ensureUserEncryptionProfile */
@@ -351,6 +368,13 @@ export class LocalEnclave<
351
368
 
352
369
  const keyPair = nacl.box.keyPair.fromSecretKey(secretKey);
353
370
 
371
+ const expectedPublicKey = this.options.expectedUserEncryptionPublicKey;
372
+ if (expectedPublicKey && base64Encode(keyPair.publicKey) !== expectedPublicKey) {
373
+ throw new Error(
374
+ "Derived encryption public key does not match expectedUserEncryptionPublicKey",
375
+ );
376
+ }
377
+
354
378
  await this.store.set(STORAGE_KEYS.USER_ID, userId);
355
379
  await this.storeObfuscated.set(STORAGE_KEYS.OBFUSCATED_PASSWORD, password);
356
380
  await this.store.delete(STORAGE_KEYS.DEPRECATED___PASSWORD);