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.cjs
CHANGED
|
@@ -3053,6 +3053,7 @@ function bufFromBytes(u) {
|
|
|
3053
3053
|
}
|
|
3054
3054
|
async function registerWebAuthnCredential(opts) {
|
|
3055
3055
|
const baseOptions = await opts.api.getWebAuthnRegisterOptions(opts.jwt, opts.rpId, opts.rpName);
|
|
3056
|
+
if (opts.allowDuplicate) delete baseOptions.excludeCredentials;
|
|
3056
3057
|
const optionsJSON = {
|
|
3057
3058
|
...baseOptions,
|
|
3058
3059
|
extensions: {
|
|
@@ -3061,11 +3062,7 @@ async function registerWebAuthnCredential(opts) {
|
|
|
3061
3062
|
}
|
|
3062
3063
|
};
|
|
3063
3064
|
const { credentialId, prfOutput, response } = await registerPasskey({ optionsJSON });
|
|
3064
|
-
|
|
3065
|
-
await opts.api.postWebAuthnRegister(opts.jwt, response, window.location.origin);
|
|
3066
|
-
} catch (e) {
|
|
3067
|
-
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);
|
|
3068
|
-
}
|
|
3065
|
+
await opts.api.postWebAuthnRegister(opts.jwt, response, window.location.origin);
|
|
3069
3066
|
return { credentialId, prfOutput };
|
|
3070
3067
|
}
|
|
3071
3068
|
|
|
@@ -3855,7 +3852,7 @@ async function createDecaneConnect(config) {
|
|
|
3855
3852
|
const pin = await config.promptPin();
|
|
3856
3853
|
return deriveKeyFromPin(pin, stored.pinSalt);
|
|
3857
3854
|
}
|
|
3858
|
-
async function registerPasskeyForDevice(userId, jwt, deviceShare) {
|
|
3855
|
+
async function registerPasskeyForDevice(userId, jwt, deviceShare, opts = {}) {
|
|
3859
3856
|
if (!isPasskeySupported()) throw new WebAuthnNotSupportedError();
|
|
3860
3857
|
const prfSalt = generateRandomBytes(32);
|
|
3861
3858
|
let credentialId;
|
|
@@ -3866,10 +3863,11 @@ async function createDecaneConnect(config) {
|
|
|
3866
3863
|
jwt,
|
|
3867
3864
|
rpId,
|
|
3868
3865
|
rpName,
|
|
3869
|
-
prfSalt
|
|
3866
|
+
prfSalt,
|
|
3867
|
+
...opts.allowDuplicate ? { allowDuplicate: true } : {}
|
|
3870
3868
|
}));
|
|
3871
3869
|
} catch (e) {
|
|
3872
|
-
if (e?.name !== "InvalidStateError") throw e;
|
|
3870
|
+
if (e?.name !== "InvalidStateError" || opts.allowDuplicate) throw e;
|
|
3873
3871
|
return adoptExistingPasskey(userId, jwt, deviceShare);
|
|
3874
3872
|
}
|
|
3875
3873
|
let key = prfOutput;
|
|
@@ -3921,7 +3919,12 @@ async function createDecaneConnect(config) {
|
|
|
3921
3919
|
}
|
|
3922
3920
|
async function adoptExistingPasskey(userId, jwt, deviceShare) {
|
|
3923
3921
|
const options = await api.getWebAuthnLoginOptions(userId, rpId);
|
|
3924
|
-
if (!options)
|
|
3922
|
+
if (!options) {
|
|
3923
|
+
console.warn(
|
|
3924
|
+
"decane-connect-kit: this authenticator holds a credential the server does not know; registering a fresh one."
|
|
3925
|
+
);
|
|
3926
|
+
return registerPasskeyForDevice(userId, jwt, deviceShare, { allowDuplicate: true });
|
|
3927
|
+
}
|
|
3925
3928
|
const prfSalt = generateRandomBytes(32);
|
|
3926
3929
|
const { response, prfOutput } = await authenticateWithPasskey({
|
|
3927
3930
|
optionsJSON: options,
|
|
@@ -3966,19 +3969,26 @@ async function createDecaneConnect(config) {
|
|
|
3966
3969
|
);
|
|
3967
3970
|
return;
|
|
3968
3971
|
}
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3972
|
+
try {
|
|
3973
|
+
const { wrappingKey, tokenKey, meta } = await passwordSetup();
|
|
3974
|
+
const iv = generateRandomBytes(12);
|
|
3975
|
+
const wrappedDeviceShare = await aesGcmEncrypt(wrappingKey, deviceShare, iv);
|
|
3976
|
+
await storage.putShare({
|
|
3977
|
+
userId,
|
|
3978
|
+
wrappedDeviceShare,
|
|
3979
|
+
iv,
|
|
3980
|
+
unlockMethod: "password",
|
|
3981
|
+
passwordSalt: meta.passwordSalt ? b64uToBuffer(meta.passwordSalt) : void 0,
|
|
3982
|
+
passwordIterations: meta.passwordIterations,
|
|
3983
|
+
version: 1
|
|
3984
|
+
});
|
|
3985
|
+
await attachUnlockToken(userId, jwt, tokenKey);
|
|
3986
|
+
} catch (e) {
|
|
3987
|
+
console.warn(
|
|
3988
|
+
"decane-connect-kit: no unlock password was set, so this device stored no share. The session works; the next visit will provision again.",
|
|
3989
|
+
e
|
|
3990
|
+
);
|
|
3991
|
+
}
|
|
3982
3992
|
}
|
|
3983
3993
|
async function firstTimeSetup(userId, jwt) {
|
|
3984
3994
|
prewarmAttestation(teeUrl);
|