decane-connect-kit 2.17.0 → 2.18.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 +32 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +32 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2971,6 +2971,7 @@ function bufFromBytes(u) {
|
|
|
2971
2971
|
}
|
|
2972
2972
|
async function registerWebAuthnCredential(opts) {
|
|
2973
2973
|
const baseOptions = await opts.api.getWebAuthnRegisterOptions(opts.jwt, opts.rpId, opts.rpName);
|
|
2974
|
+
if (opts.allowDuplicate) delete baseOptions.excludeCredentials;
|
|
2974
2975
|
const optionsJSON = {
|
|
2975
2976
|
...baseOptions,
|
|
2976
2977
|
extensions: {
|
|
@@ -2979,11 +2980,7 @@ async function registerWebAuthnCredential(opts) {
|
|
|
2979
2980
|
}
|
|
2980
2981
|
};
|
|
2981
2982
|
const { credentialId, prfOutput, response } = await registerPasskey({ optionsJSON });
|
|
2982
|
-
|
|
2983
|
-
await opts.api.postWebAuthnRegister(opts.jwt, response, window.location.origin);
|
|
2984
|
-
} catch (e) {
|
|
2985
|
-
console.warn("decane-connect-kit: WebAuthn server-side registration failed; PRF-based unlock still works, but rotateShares()/exportPortableBackup() will not until this is retried.", e);
|
|
2986
|
-
}
|
|
2983
|
+
await opts.api.postWebAuthnRegister(opts.jwt, response, window.location.origin);
|
|
2987
2984
|
return { credentialId, prfOutput };
|
|
2988
2985
|
}
|
|
2989
2986
|
|
|
@@ -3773,7 +3770,7 @@ async function createDecaneConnect(config) {
|
|
|
3773
3770
|
const pin = await config.promptPin();
|
|
3774
3771
|
return deriveKeyFromPin(pin, stored.pinSalt);
|
|
3775
3772
|
}
|
|
3776
|
-
async function registerPasskeyForDevice(userId, jwt, deviceShare) {
|
|
3773
|
+
async function registerPasskeyForDevice(userId, jwt, deviceShare, opts = {}) {
|
|
3777
3774
|
if (!isPasskeySupported()) throw new WebAuthnNotSupportedError();
|
|
3778
3775
|
const prfSalt = generateRandomBytes(32);
|
|
3779
3776
|
let credentialId;
|
|
@@ -3784,10 +3781,11 @@ async function createDecaneConnect(config) {
|
|
|
3784
3781
|
jwt,
|
|
3785
3782
|
rpId,
|
|
3786
3783
|
rpName,
|
|
3787
|
-
prfSalt
|
|
3784
|
+
prfSalt,
|
|
3785
|
+
...opts.allowDuplicate ? { allowDuplicate: true } : {}
|
|
3788
3786
|
}));
|
|
3789
3787
|
} catch (e) {
|
|
3790
|
-
if (e?.name !== "InvalidStateError") throw e;
|
|
3788
|
+
if (e?.name !== "InvalidStateError" || opts.allowDuplicate) throw e;
|
|
3791
3789
|
return adoptExistingPasskey(userId, jwt, deviceShare);
|
|
3792
3790
|
}
|
|
3793
3791
|
let key = prfOutput;
|
|
@@ -3839,7 +3837,12 @@ async function createDecaneConnect(config) {
|
|
|
3839
3837
|
}
|
|
3840
3838
|
async function adoptExistingPasskey(userId, jwt, deviceShare) {
|
|
3841
3839
|
const options = await api.getWebAuthnLoginOptions(userId, rpId);
|
|
3842
|
-
if (!options)
|
|
3840
|
+
if (!options) {
|
|
3841
|
+
console.warn(
|
|
3842
|
+
"decane-connect-kit: this authenticator holds a credential the server does not know; registering a fresh one."
|
|
3843
|
+
);
|
|
3844
|
+
return registerPasskeyForDevice(userId, jwt, deviceShare, { allowDuplicate: true });
|
|
3845
|
+
}
|
|
3843
3846
|
const prfSalt = generateRandomBytes(32);
|
|
3844
3847
|
const { response, prfOutput } = await authenticateWithPasskey({
|
|
3845
3848
|
optionsJSON: options,
|
|
@@ -3884,19 +3887,26 @@ async function createDecaneConnect(config) {
|
|
|
3884
3887
|
);
|
|
3885
3888
|
return;
|
|
3886
3889
|
}
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3890
|
+
try {
|
|
3891
|
+
const { wrappingKey, tokenKey, meta } = await passwordSetup();
|
|
3892
|
+
const iv = generateRandomBytes(12);
|
|
3893
|
+
const wrappedDeviceShare = await aesGcmEncrypt(wrappingKey, deviceShare, iv);
|
|
3894
|
+
await storage.putShare({
|
|
3895
|
+
userId,
|
|
3896
|
+
wrappedDeviceShare,
|
|
3897
|
+
iv,
|
|
3898
|
+
unlockMethod: "password",
|
|
3899
|
+
passwordSalt: meta.passwordSalt ? b64uToBuffer(meta.passwordSalt) : void 0,
|
|
3900
|
+
passwordIterations: meta.passwordIterations,
|
|
3901
|
+
version: 1
|
|
3902
|
+
});
|
|
3903
|
+
await attachUnlockToken(userId, jwt, tokenKey);
|
|
3904
|
+
} catch (e) {
|
|
3905
|
+
console.warn(
|
|
3906
|
+
"decane-connect-kit: no unlock password was set, so this device stored no share. The session works; the next visit will provision again.",
|
|
3907
|
+
e
|
|
3908
|
+
);
|
|
3909
|
+
}
|
|
3900
3910
|
}
|
|
3901
3911
|
async function firstTimeSetup(userId, jwt) {
|
|
3902
3912
|
prewarmAttestation(teeUrl);
|