decane-connect-kit 2.8.0 → 2.9.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
@@ -3694,20 +3694,17 @@ async function createDecaneConnect(config) {
3694
3694
  const pin = await config.promptPin();
3695
3695
  return deriveKeyFromPin(pin, stored.pinSalt);
3696
3696
  }
3697
- async function registerPasskeyAndBackup(userId, jwt, deviceShare) {
3698
- if (!isPasskeySupported()) return;
3697
+ async function registerPasskeyForDevice(userId, jwt, deviceShare) {
3698
+ if (!isPasskeySupported()) throw new WebAuthnNotSupportedError();
3699
3699
  const prfSalt = generateRandomBytes(32);
3700
- let credentialId;
3701
- let prfOutput;
3702
- try {
3703
- const result = await registerWebAuthnCredential({ api, jwt, rpId, rpName, prfSalt });
3704
- credentialId = result.credentialId;
3705
- prfOutput = result.prfOutput;
3706
- } catch (e) {
3707
- console.warn("decane-connect-kit: passkey provisioning after recovery failed; user can set this up later.", e);
3708
- return;
3709
- }
3710
- if (!prfOutput) return;
3700
+ const { credentialId, prfOutput } = await registerWebAuthnCredential({
3701
+ api,
3702
+ jwt,
3703
+ rpId,
3704
+ rpName,
3705
+ prfSalt
3706
+ });
3707
+ if (!prfOutput) throw new WebAuthnNotSupportedError();
3711
3708
  const wrappingKey = await importAesKey(prfOutput);
3712
3709
  const iv = generateRandomBytes(12);
3713
3710
  const wrappedDeviceShare = await aesGcmEncrypt(wrappingKey, deviceShare, iv);
@@ -3732,6 +3729,17 @@ async function createDecaneConnect(config) {
3732
3729
  console.warn("decane-connect-kit: wrapped share backup upload failed; user can retry from settings.", e);
3733
3730
  }
3734
3731
  }
3732
+ async function registerPasskeyAndBackup(userId, jwt, deviceShare) {
3733
+ if (!isPasskeySupported()) return;
3734
+ try {
3735
+ await registerPasskeyForDevice(userId, jwt, deviceShare);
3736
+ } catch (e) {
3737
+ console.warn(
3738
+ "decane-connect-kit: passkey provisioning failed; the user can set one up later with addPasskey().",
3739
+ e
3740
+ );
3741
+ }
3742
+ }
3735
3743
  async function firstTimeSetup(userId, jwt) {
3736
3744
  prewarmAttestation(teeUrl);
3737
3745
  let unlockMethod;
@@ -4181,6 +4189,34 @@ async function createDecaneConnect(config) {
4181
4189
  if (!candidate) throw new NewDeviceError();
4182
4190
  return passkeyLogin(candidate);
4183
4191
  },
4192
+ async hasPasskey() {
4193
+ if (!auth) return false;
4194
+ const stored = await storage.getShare(auth.userId);
4195
+ return stored?.unlockMethod === "passkey";
4196
+ },
4197
+ async addPasskey() {
4198
+ if (!auth) throw new ReconnectRequiredError();
4199
+ if (!isPasskeySupported()) throw new WebAuthnNotSupportedError();
4200
+ const stored = await storage.getShare(auth.userId);
4201
+ if (!stored) throw new NewDeviceError();
4202
+ if (stored.unlockMethod === "passkey") return;
4203
+ let deviceShare;
4204
+ try {
4205
+ deviceShare = await aesGcmDecrypt(
4206
+ await getWrappingKey(stored),
4207
+ stored.wrappedDeviceShare,
4208
+ stored.iv
4209
+ );
4210
+ } catch (e) {
4211
+ if (e instanceof DecaneConnectError) throw e;
4212
+ throw new ShareCorruptedError();
4213
+ }
4214
+ try {
4215
+ await registerPasskeyForDevice(auth.userId, auth.jwt, deviceShare);
4216
+ } finally {
4217
+ zeroize(deviceShare);
4218
+ }
4219
+ },
4184
4220
  async unlock() {
4185
4221
  if (!auth) {
4186
4222
  const candidate = await passkeyLoginCandidate();
@@ -6940,6 +6976,16 @@ function DecaneKit({ config, children }) {
6940
6976
  if (!sdk) throw new Error("Social wallet not connected");
6941
6977
  return sdk.exportPortableBackup(opts);
6942
6978
  }, []);
6979
+ const socialHasPasskey = (0, import_react5.useCallback)(async () => {
6980
+ const sdk = socialRef.current;
6981
+ if (!sdk) throw new Error("Social wallet not connected");
6982
+ return sdk.hasPasskey();
6983
+ }, []);
6984
+ const socialAddPasskey = (0, import_react5.useCallback)(async () => {
6985
+ const sdk = socialRef.current;
6986
+ if (!sdk) throw new Error("Social wallet not connected");
6987
+ return sdk.addPasskey();
6988
+ }, []);
6943
6989
  const socialHasRecoveryShare = (0, import_react5.useCallback)(async () => {
6944
6990
  const sdk = socialRef.current;
6945
6991
  if (!sdk) throw new Error("Social wallet not connected");
@@ -7001,6 +7047,8 @@ function DecaneKit({ config, children }) {
7001
7047
  socialRotateShares,
7002
7048
  socialExportPortableBackup,
7003
7049
  socialHasRecoveryShare,
7050
+ socialHasPasskey,
7051
+ socialAddPasskey,
7004
7052
  socialShouldPromptRecovery,
7005
7053
  socialDismissRecoveryPrompt,
7006
7054
  socialModalOpen,
@@ -7079,6 +7127,7 @@ function useSocialAuth() {
7079
7127
  const {
7080
7128
  socialAuth,
7081
7129
  connectWithGoogle,
7130
+ connectWithKingsChat,
7082
7131
  connectWithEmail,
7083
7132
  verifyEmailCode: verifyEmailCode2,
7084
7133
  connectWithPhone,
@@ -7091,6 +7140,7 @@ function useSocialAuth() {
7091
7140
  socialDisconnect
7092
7141
  } = useDecaneContext();
7093
7142
  const [googleLoading, setGoogleLoading] = (0, import_react6.useState)(false);
7143
+ const [kingschatLoading, setKingschatLoading] = (0, import_react6.useState)(false);
7094
7144
  const [emailLoading, setEmailLoading] = (0, import_react6.useState)(false);
7095
7145
  const [phoneLoading, setPhoneLoading] = (0, import_react6.useState)(false);
7096
7146
  const [tokenLoading, setTokenLoading] = (0, import_react6.useState)(false);
@@ -7106,6 +7156,18 @@ function useSocialAuth() {
7106
7156
  setGoogleLoading(false);
7107
7157
  }
7108
7158
  }, [connectWithGoogle]);
7159
+ const signInWithKingsChat = (0, import_react6.useCallback)(async () => {
7160
+ setKingschatLoading(true);
7161
+ setError(null);
7162
+ try {
7163
+ await connectWithKingsChat();
7164
+ } catch (e) {
7165
+ setError(e.message);
7166
+ throw e;
7167
+ } finally {
7168
+ setKingschatLoading(false);
7169
+ }
7170
+ }, [connectWithKingsChat]);
7109
7171
  const sendEmailCode = (0, import_react6.useCallback)(async (email) => {
7110
7172
  setEmailLoading(true);
7111
7173
  setError(null);
@@ -7225,6 +7287,7 @@ function useSocialAuth() {
7225
7287
  // this into a real reconnect (signInWithGoogle / sendEmailCode), not unlock().
7226
7288
  needsReconnect: socialAuth.needsReconnect,
7227
7289
  googleLoading,
7290
+ kingschatLoading,
7228
7291
  emailLoading,
7229
7292
  phoneLoading,
7230
7293
  tokenLoading,
@@ -7233,6 +7296,7 @@ function useSocialAuth() {
7233
7296
  error,
7234
7297
  clearError: () => setError(null),
7235
7298
  signInWithGoogle,
7299
+ signInWithKingsChat,
7236
7300
  sendEmailCode,
7237
7301
  confirmEmailCode,
7238
7302
  sendPhoneCode,
@@ -7264,6 +7328,8 @@ function useSocialWallet() {
7264
7328
  socialRotateShares,
7265
7329
  socialExportPortableBackup,
7266
7330
  socialHasRecoveryShare,
7331
+ socialHasPasskey,
7332
+ socialAddPasskey,
7267
7333
  socialShouldPromptRecovery,
7268
7334
  socialDismissRecoveryPrompt,
7269
7335
  openSocialModal,
@@ -7351,6 +7417,16 @@ function useSocialWallet() {
7351
7417
  (opts) => run(() => socialExportPortableBackup(opts)),
7352
7418
  [socialExportPortableBackup]
7353
7419
  );
7420
+ const hasPasskey = (0, import_react6.useCallback)(() => run(() => socialHasPasskey()), [socialHasPasskey]);
7421
+ const addPasskey = (0, import_react6.useCallback)(async () => {
7422
+ setError(null);
7423
+ try {
7424
+ await socialAddPasskey();
7425
+ } catch (e) {
7426
+ setError(e.message);
7427
+ throw e;
7428
+ }
7429
+ }, [socialAddPasskey]);
7354
7430
  const hasRecoveryShare = (0, import_react6.useCallback)(
7355
7431
  () => run(() => socialHasRecoveryShare()),
7356
7432
  [socialHasRecoveryShare]
@@ -7404,6 +7480,9 @@ function useSocialWallet() {
7404
7480
  // The Decane JWT — authenticate the user to your own backend (bundler proxy,
7405
7481
  // etc.); verify server-side against backend.decane.app/.well-known/jwks.json.
7406
7482
  getAccessToken: socialGetAccessToken,
7483
+ // Passkey management for THIS device
7484
+ hasPasskey,
7485
+ addPasskey,
7407
7486
  // Recovery (2-of-3 Shamir share set)
7408
7487
  rotateShares,
7409
7488
  exportPortableBackup,