decane-connect-kit 2.16.0 → 2.17.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/dist/index.cjs CHANGED
@@ -3858,13 +3858,20 @@ async function createDecaneConnect(config) {
3858
3858
  async function registerPasskeyForDevice(userId, jwt, deviceShare) {
3859
3859
  if (!isPasskeySupported()) throw new WebAuthnNotSupportedError();
3860
3860
  const prfSalt = generateRandomBytes(32);
3861
- const { credentialId, prfOutput } = await registerWebAuthnCredential({
3862
- api,
3863
- jwt,
3864
- rpId,
3865
- rpName,
3866
- prfSalt
3867
- });
3861
+ let credentialId;
3862
+ let prfOutput;
3863
+ try {
3864
+ ({ credentialId, prfOutput } = await registerWebAuthnCredential({
3865
+ api,
3866
+ jwt,
3867
+ rpId,
3868
+ rpName,
3869
+ prfSalt
3870
+ }));
3871
+ } catch (e) {
3872
+ if (e?.name !== "InvalidStateError") throw e;
3873
+ return adoptExistingPasskey(userId, jwt, deviceShare);
3874
+ }
3868
3875
  let key = prfOutput;
3869
3876
  if (!key) {
3870
3877
  try {
@@ -3877,7 +3884,10 @@ async function createDecaneConnect(config) {
3877
3884
  }
3878
3885
  }
3879
3886
  if (!key) throw new WebAuthnNotSupportedError();
3880
- const wrappingKey = await importAesKey(key);
3887
+ await storeShareUnderPasskey(userId, jwt, deviceShare, credentialId, key, prfSalt);
3888
+ }
3889
+ async function storeShareUnderPasskey(userId, jwt, deviceShare, credentialId, prfOutput, prfSalt) {
3890
+ const wrappingKey = await importAesKey(prfOutput);
3881
3891
  const iv = generateRandomBytes(12);
3882
3892
  const wrappedDeviceShare = await aesGcmEncrypt(wrappingKey, deviceShare, iv);
3883
3893
  const existing = await storage.getShare(userId);
@@ -3909,6 +3919,24 @@ async function createDecaneConnect(config) {
3909
3919
  console.warn("decane-connect-kit: wrapped share backup upload failed; user can retry from settings.", e);
3910
3920
  }
3911
3921
  }
3922
+ async function adoptExistingPasskey(userId, jwt, deviceShare) {
3923
+ const options = await api.getWebAuthnLoginOptions(userId, rpId);
3924
+ if (!options) throw new WebAuthnNotSupportedError();
3925
+ const prfSalt = generateRandomBytes(32);
3926
+ const { response, prfOutput } = await authenticateWithPasskey({
3927
+ optionsJSON: options,
3928
+ prfSalt
3929
+ });
3930
+ if (!prfOutput) throw new WebAuthnNotSupportedError();
3931
+ await storeShareUnderPasskey(
3932
+ userId,
3933
+ jwt,
3934
+ deviceShare,
3935
+ b64uToBuffer(response.id),
3936
+ prfOutput,
3937
+ prfSalt
3938
+ );
3939
+ }
3912
3940
  async function registerPasskeyAndBackup(userId, jwt, deviceShare) {
3913
3941
  if (!isPasskeySupported()) return;
3914
3942
  try {