@better-auth/passkey 1.7.0-beta.4 → 1.7.0-beta.5

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/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as PasskeyExtensionsResolver, c as PasskeyRegistrationUser, i as PasskeyAuthenticationOptions, l as WebAuthnChallengeValue, n as PASSKEY_ERROR_CODES, o as PasskeyOptions, r as Passkey, s as PasskeyRegistrationOptions, t as passkey } from "./index-BoC1i3hA.mjs";
1
+ import { a as Passkey, c as PasskeyOptions, d as WebAuthnChallengeValue, l as PasskeyRegistrationOptions, n as PASSKEY_ERROR_CODES, o as PasskeyAuthenticationOptions, s as PasskeyExtensionsResolver, t as passkey, u as PasskeyRegistrationUser } from "./index-Ci52vhOT.mjs";
2
2
  import { AuthenticationExtensionsClientInputs, AuthenticationExtensionsClientOutputs, AuthenticationResponseJSON, RegistrationResponseJSON } from "@simplewebauthn/server";
3
3
  import * as better_auth_client0 from "better-auth/client";
4
4
  import * as nanostores from "nanostores";
package/dist/client.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as PASSKEY_ERROR_CODES, t as PACKAGE_VERSION } from "./version-D_0sS5d6.mjs";
1
+ import { n as PASSKEY_ERROR_CODES, t as PACKAGE_VERSION } from "./version-tMqL0F6x.mjs";
2
2
  import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
3
3
  import { useAuthQuery } from "better-auth/client";
4
4
  import { atom } from "nanostores";
@@ -100,7 +100,13 @@ interface PasskeyRegistrationOptions {
100
100
  }) => Awaitable<PasskeyRegistrationUser>) | undefined;
101
101
  /**
102
102
  * Callback after a successful registration verification.
103
- * Useful for user linking or auditing.
103
+ * Useful for user linking, auditing, or labeling the passkey.
104
+ *
105
+ * Return `userId` to attribute the passkey to a different user. Return `name`
106
+ * to set the stored label when the client did not provide one; the AAGUID is
107
+ * available via `verification.registrationInfo?.aaguid`. A non-empty
108
+ * client-supplied name always takes precedence over the returned `name`;
109
+ * whitespace-only input is treated as absent.
104
110
  */
105
111
  afterVerification?: ((args: {
106
112
  ctx: GenericEndpointContext;
@@ -110,6 +116,7 @@ interface PasskeyRegistrationOptions {
110
116
  context?: string | null | undefined;
111
117
  }) => Awaitable<{
112
118
  userId?: string;
119
+ name?: string;
113
120
  } | void>) | undefined;
114
121
  /**
115
122
  * Optional WebAuthn extensions to include in registration options.
@@ -196,6 +203,30 @@ type Passkey = {
196
203
  aaguid?: string | undefined;
197
204
  };
198
205
  //#endregion
206
+ //#region src/authenticator-metadata.d.ts
207
+ /**
208
+ * Best-effort map of common authenticator AAGUIDs to a human-readable provider
209
+ * name, for labeling passkeys in management UIs.
210
+ *
211
+ * An AAGUID identifies an authenticator *model* (not a device or a user) and is
212
+ * present only in the registration response. Better Auth stores it on every
213
+ * passkey row and returns it from `listPasskeys`, so a display label can be
214
+ * resolved wherever passkeys are rendered.
215
+ *
216
+ * This list is intentionally small and not authoritative. Many authenticators
217
+ * are missing, and privacy-preserving platforms report an all-zero AAGUID
218
+ * (`00000000-0000-0000-0000-000000000000`) that matches nothing here. Notably,
219
+ * Apple devices zero the AAGUID under the default `attestation: "none"` flow, so
220
+ * the Apple entries below only appear in attested or managed contexts. For full
221
+ * coverage, resolve against the community-maintained source instead:
222
+ *
223
+ * - https://github.com/passkeydeveloper/passkey-authenticator-aaguids
224
+ *
225
+ * Names mirror that source verbatim.
226
+ */
227
+ declare const commonAuthenticatorNames: Record<string, string>;
228
+ declare const getAuthenticatorName: (aaguid: string | null | undefined) => string | undefined;
229
+ //#endregion
199
230
  //#region src/error-codes.d.ts
200
231
  declare const PASSKEY_ERROR_CODES: {
201
232
  CHALLENGE_NOT_FOUND: better_auth0.RawError<"CHALLENGE_NOT_FOUND">;
@@ -817,4 +848,4 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
817
848
  options: PasskeyOptions | undefined;
818
849
  };
819
850
  //#endregion
820
- export { PasskeyExtensionsResolver as a, PasskeyRegistrationUser as c, PasskeyAuthenticationOptions as i, WebAuthnChallengeValue as l, PASSKEY_ERROR_CODES as n, PasskeyOptions as o, Passkey as r, PasskeyRegistrationOptions as s, passkey as t };
851
+ export { Passkey as a, PasskeyOptions as c, WebAuthnChallengeValue as d, getAuthenticatorName as i, PasskeyRegistrationOptions as l, PASSKEY_ERROR_CODES as n, PasskeyAuthenticationOptions as o, commonAuthenticatorNames as r, PasskeyExtensionsResolver as s, passkey as t, PasskeyRegistrationUser as u };
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as PASSKEY_ERROR_CODES, o as PasskeyOptions, r as Passkey, t as passkey } from "./index-BoC1i3hA.mjs";
2
- export { PASSKEY_ERROR_CODES, Passkey, PasskeyOptions, passkey };
1
+ import { a as Passkey, c as PasskeyOptions, i as getAuthenticatorName, n as PASSKEY_ERROR_CODES, r as commonAuthenticatorNames, t as passkey } from "./index-Ci52vhOT.mjs";
2
+ export { PASSKEY_ERROR_CODES, Passkey, PasskeyOptions, commonAuthenticatorNames, getAuthenticatorName, passkey };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as PASSKEY_ERROR_CODES, t as PACKAGE_VERSION } from "./version-D_0sS5d6.mjs";
1
+ import { n as PASSKEY_ERROR_CODES, t as PACKAGE_VERSION } from "./version-tMqL0F6x.mjs";
2
2
  import { mergeSchema } from "better-auth/db";
3
3
  import { createAuthEndpoint } from "@better-auth/core/api";
4
4
  import { APIError } from "@better-auth/core/error";
@@ -287,7 +287,7 @@ const generatePasskeyAuthenticationOptions = (opts, { maxAgeInSeconds }) => crea
287
287
  });
288
288
  const verifyPasskeyRegistrationBodySchema = z.object({
289
289
  response: z.any(),
290
- name: z.string().meta({ description: "Name of the passkey" }).optional()
290
+ name: z.string().trim().meta({ description: "Name of the passkey" }).optional()
291
291
  });
292
292
  const verifyPasskeyRegistration = (options) => {
293
293
  const requireSession = options.registration?.requireSession ?? true;
@@ -335,6 +335,7 @@ const verifyPasskeyRegistration = (options) => {
335
335
  displayName: userData.displayName
336
336
  };
337
337
  let targetUserId = resolvedUser.id;
338
+ let resolvedName = ctx.body.name || void 0;
338
339
  if (options.registration?.afterVerification) {
339
340
  const result = await options.registration.afterVerification({
340
341
  ctx,
@@ -348,10 +349,11 @@ const verifyPasskeyRegistration = (options) => {
348
349
  if (session?.user?.id && result.userId !== session.user.id) throw APIError.from("UNAUTHORIZED", PASSKEY_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY);
349
350
  targetUserId = result.userId;
350
351
  }
352
+ if (!resolvedName) resolvedName = result?.name?.trim() || void 0;
351
353
  }
352
354
  const pubKey = base64.encode(credential.publicKey);
353
355
  const newPasskey = {
354
- name: ctx.body.name,
356
+ name: resolvedName,
355
357
  userId: targetUserId,
356
358
  credentialID: credential.id,
357
359
  publicKey: pubKey,
@@ -576,7 +578,7 @@ const updatePasskey = createAuthEndpoint("/passkey/update-passkey", {
576
578
  method: "POST",
577
579
  body: z.object({
578
580
  id: z.string().meta({ description: `The ID of the passkey which will be updated. Eg: \"passkey-id\"` }),
579
- name: z.string().meta({ description: `The new name which the passkey will be updated to. Eg: \"my-new-passkey-name\"` })
581
+ name: z.string().trim().min(1).meta({ description: `The new name which the passkey will be updated to. Eg: \"my-new-passkey-name\"` })
580
582
  }),
581
583
  use: [sessionMiddleware, requireResourceOwnership({
582
584
  model: "passkey",
@@ -660,6 +662,63 @@ const schema = { passkey: { fields: {
660
662
  }
661
663
  } } };
662
664
  //#endregion
665
+ //#region src/authenticator-metadata.ts
666
+ /**
667
+ * Best-effort map of common authenticator AAGUIDs to a human-readable provider
668
+ * name, for labeling passkeys in management UIs.
669
+ *
670
+ * An AAGUID identifies an authenticator *model* (not a device or a user) and is
671
+ * present only in the registration response. Better Auth stores it on every
672
+ * passkey row and returns it from `listPasskeys`, so a display label can be
673
+ * resolved wherever passkeys are rendered.
674
+ *
675
+ * This list is intentionally small and not authoritative. Many authenticators
676
+ * are missing, and privacy-preserving platforms report an all-zero AAGUID
677
+ * (`00000000-0000-0000-0000-000000000000`) that matches nothing here. Notably,
678
+ * Apple devices zero the AAGUID under the default `attestation: "none"` flow, so
679
+ * the Apple entries below only appear in attested or managed contexts. For full
680
+ * coverage, resolve against the community-maintained source instead:
681
+ *
682
+ * - https://github.com/passkeydeveloper/passkey-authenticator-aaguids
683
+ *
684
+ * Names mirror that source verbatim.
685
+ */
686
+ const commonAuthenticatorNames = {
687
+ "ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4": "Google Password Manager",
688
+ "fbfc3007-154e-4ecc-8c0b-6e020557d7bd": "Apple Passwords",
689
+ "dd4ec289-e01d-41c9-bb89-70fa845d4bf2": "iCloud Keychain (Managed)",
690
+ "08987058-cadc-4b81-b6e1-30de50dcbe96": "Windows Hello",
691
+ "9ddd1817-af5a-4672-a2b9-3e3dd95000a9": "Windows Hello",
692
+ "6028b017-b1d4-4c02-b4b3-afcdafc96bb2": "Windows Hello",
693
+ "bada5566-a7aa-401f-bd96-45619a55120d": "1Password",
694
+ "d548826e-79b4-db40-a3d8-11116f7e8349": "Bitwarden",
695
+ "531126d6-e717-415c-9320-3d9aa6981239": "Dashlane",
696
+ "b78a0a55-6ef8-d246-a042-ba0f6d55050c": "LastPass",
697
+ "b84e4048-15dc-4dd0-8640-f4f60813c8af": "NordPass",
698
+ "50726f74-6f6e-5061-7373-50726f746f6e": "Proton Pass",
699
+ "0ea242b4-43c4-4a1b-8b17-dd6d0b6baec6": "Keeper",
700
+ "53414d53-554e-4700-0000-000000000000": "Samsung Pass"
701
+ };
702
+ /**
703
+ * Resolve a best-effort provider name for an authenticator AAGUID.
704
+ *
705
+ * Returns `undefined` when the AAGUID is unknown, empty, or the all-zero value
706
+ * reported by privacy-preserving platforms. Casing and surrounding whitespace
707
+ * are normalized before lookup.
708
+ *
709
+ * @example
710
+ * ```ts
711
+ * const label = passkey.name || getAuthenticatorName(passkey.aaguid) || "Passkey";
712
+ * ```
713
+ */
714
+ const ANONYMOUS_AAGUID = "00000000-0000-0000-0000-000000000000";
715
+ const getAuthenticatorName = (aaguid) => {
716
+ const normalized = aaguid?.trim().toLowerCase();
717
+ if (!normalized || normalized === ANONYMOUS_AAGUID) return void 0;
718
+ const name = commonAuthenticatorNames[normalized];
719
+ return typeof name === "string" ? name : void 0;
720
+ };
721
+ //#endregion
663
722
  //#region src/index.ts
664
723
  const MAX_AGE_IN_SECONDS = 300;
665
724
  const passkey = (options) => {
@@ -689,4 +748,4 @@ const passkey = (options) => {
689
748
  };
690
749
  };
691
750
  //#endregion
692
- export { PASSKEY_ERROR_CODES, passkey };
751
+ export { PASSKEY_ERROR_CODES, commonAuthenticatorNames, getAuthenticatorName, passkey };
@@ -18,6 +18,6 @@ const PASSKEY_ERROR_CODES = defineErrorCodes({
18
18
  });
19
19
  //#endregion
20
20
  //#region src/version.ts
21
- const PACKAGE_VERSION = "1.7.0-beta.4";
21
+ const PACKAGE_VERSION = "1.7.0-beta.5";
22
22
  //#endregion
23
23
  export { PASSKEY_ERROR_CODES as n, PACKAGE_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/passkey",
3
- "version": "1.7.0-beta.4",
3
+ "version": "1.7.0-beta.5",
4
4
  "description": "Passkey plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -55,16 +55,16 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "tsdown": "0.21.1",
58
- "@better-auth/core": "1.7.0-beta.4",
59
- "better-auth": "1.7.0-beta.4"
58
+ "@better-auth/core": "1.7.0-beta.5",
59
+ "better-auth": "1.7.0-beta.5"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@better-auth/utils": "0.4.1",
63
- "@better-fetch/fetch": "1.1.21",
64
- "better-call": "1.3.5",
63
+ "@better-fetch/fetch": "1.2.2",
64
+ "better-call": "1.3.6",
65
65
  "nanostores": "^1.0.1",
66
- "@better-auth/core": "^1.7.0-beta.4",
67
- "better-auth": "^1.7.0-beta.4"
66
+ "@better-auth/core": "^1.7.0-beta.5",
67
+ "better-auth": "^1.7.0-beta.5"
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsdown",