@better-auth/passkey 1.5.0-beta.11 → 1.5.0-beta.13

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 { i as WebAuthnChallengeValue, n as Passkey, r as PasskeyOptions, t as passkey } from "./index-YkeSH-Ft.mjs";
1
+ import { i as WebAuthnChallengeValue, n as Passkey, r as PasskeyOptions, t as passkey } from "./index-BQvTl2Qj.mjs";
2
2
  import * as better_auth_client0 from "better-auth/client";
3
3
  import * as nanostores0 from "nanostores";
4
4
  import { atom } from "nanostores";
@@ -1,7 +1,7 @@
1
1
  import * as _simplewebauthn_server0 from "@simplewebauthn/server";
2
2
  import { CredentialDeviceType } from "@simplewebauthn/server";
3
3
  import * as zod0 from "zod";
4
- import * as better_auth0 from "better-auth";
4
+ import * as better_auth6 from "better-auth";
5
5
  import { InferOptionSchema } from "better-auth/types";
6
6
  import * as better_call0 from "better-call";
7
7
 
@@ -158,7 +158,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
158
158
  updatedAt: Date;
159
159
  email: string;
160
160
  emailVerified: boolean;
161
- name?: string | null | undefined;
161
+ name: string;
162
162
  image?: string | null | undefined;
163
163
  };
164
164
  };
@@ -169,7 +169,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
169
169
  "cross-platform": "cross-platform";
170
170
  }>>;
171
171
  name: zod0.ZodOptional<zod0.ZodString>;
172
- }, better_auth0.$strip>>;
172
+ }, better_auth6.$strip>>;
173
173
  metadata: {
174
174
  openapi: {
175
175
  operationId: string;
@@ -387,7 +387,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
387
387
  body: zod0.ZodObject<{
388
388
  response: zod0.ZodAny;
389
389
  name: zod0.ZodOptional<zod0.ZodString>;
390
- }, better_auth0.$strip>;
390
+ }, better_auth6.$strip>;
391
391
  use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
392
392
  session: {
393
393
  session: Record<string, any> & {
@@ -406,7 +406,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
406
406
  updatedAt: Date;
407
407
  email: string;
408
408
  emailVerified: boolean;
409
- name?: string | null | undefined;
409
+ name: string;
410
410
  image?: string | null | undefined;
411
411
  };
412
412
  };
@@ -437,7 +437,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
437
437
  method: "POST";
438
438
  body: zod0.ZodObject<{
439
439
  response: zod0.ZodRecord<zod0.ZodAny, zod0.ZodAny>;
440
- }, better_auth0.$strip>;
440
+ }, better_auth6.$strip>;
441
441
  metadata: {
442
442
  openapi: {
443
443
  operationId: string;
@@ -501,7 +501,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
501
501
  updatedAt: Date;
502
502
  email: string;
503
503
  emailVerified: boolean;
504
- name?: string | null | undefined;
504
+ name: string;
505
505
  image?: string | null | undefined;
506
506
  };
507
507
  };
@@ -533,7 +533,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
533
533
  method: "POST";
534
534
  body: zod0.ZodObject<{
535
535
  id: zod0.ZodString;
536
- }, better_auth0.$strip>;
536
+ }, better_auth6.$strip>;
537
537
  use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
538
538
  session: {
539
539
  session: Record<string, any> & {
@@ -552,7 +552,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
552
552
  updatedAt: Date;
553
553
  email: string;
554
554
  emailVerified: boolean;
555
- name?: string | null | undefined;
555
+ name: string;
556
556
  image?: string | null | undefined;
557
557
  };
558
558
  };
@@ -589,7 +589,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
589
589
  body: zod0.ZodObject<{
590
590
  id: zod0.ZodString;
591
591
  name: zod0.ZodString;
592
- }, better_auth0.$strip>;
592
+ }, better_auth6.$strip>;
593
593
  use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
594
594
  session: {
595
595
  session: Record<string, any> & {
@@ -608,7 +608,7 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
608
608
  updatedAt: Date;
609
609
  email: string;
610
610
  emailVerified: boolean;
611
- name?: string | null | undefined;
611
+ name: string;
612
612
  image?: string | null | undefined;
613
613
  };
614
614
  };
@@ -693,16 +693,16 @@ declare const passkey: (options?: PasskeyOptions | undefined) => {
693
693
  };
694
694
  };
695
695
  $ERROR_CODES: {
696
- CHALLENGE_NOT_FOUND: better_auth0.RawError<"CHALLENGE_NOT_FOUND">;
697
- YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: better_auth0.RawError<"YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY">;
698
- FAILED_TO_VERIFY_REGISTRATION: better_auth0.RawError<"FAILED_TO_VERIFY_REGISTRATION">;
699
- PASSKEY_NOT_FOUND: better_auth0.RawError<"PASSKEY_NOT_FOUND">;
700
- AUTHENTICATION_FAILED: better_auth0.RawError<"AUTHENTICATION_FAILED">;
701
- UNABLE_TO_CREATE_SESSION: better_auth0.RawError<"UNABLE_TO_CREATE_SESSION">;
702
- FAILED_TO_UPDATE_PASSKEY: better_auth0.RawError<"FAILED_TO_UPDATE_PASSKEY">;
696
+ CHALLENGE_NOT_FOUND: better_auth6.RawError<"CHALLENGE_NOT_FOUND">;
697
+ YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: better_auth6.RawError<"YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY">;
698
+ FAILED_TO_VERIFY_REGISTRATION: better_auth6.RawError<"FAILED_TO_VERIFY_REGISTRATION">;
699
+ PASSKEY_NOT_FOUND: better_auth6.RawError<"PASSKEY_NOT_FOUND">;
700
+ AUTHENTICATION_FAILED: better_auth6.RawError<"AUTHENTICATION_FAILED">;
701
+ UNABLE_TO_CREATE_SESSION: better_auth6.RawError<"UNABLE_TO_CREATE_SESSION">;
702
+ FAILED_TO_UPDATE_PASSKEY: better_auth6.RawError<"FAILED_TO_UPDATE_PASSKEY">;
703
703
  };
704
704
  options: PasskeyOptions | undefined;
705
705
  };
706
706
  //#endregion
707
707
  export { WebAuthnChallengeValue as i, Passkey as n, PasskeyOptions as r, passkey as t };
708
- //# sourceMappingURL=index-YkeSH-Ft.d.mts.map
708
+ //# sourceMappingURL=index-BQvTl2Qj.d.mts.map
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as Passkey, r as PasskeyOptions, t as passkey } from "./index-YkeSH-Ft.mjs";
1
+ import { n as Passkey, r as PasskeyOptions, t as passkey } from "./index-BQvTl2Qj.mjs";
2
2
  export { Passkey, PasskeyOptions, passkey };
package/dist/index.mjs CHANGED
@@ -20,7 +20,7 @@ const generatePasskeyQuerySchema = z.object({
20
20
  authenticatorAttachment: z.enum(["platform", "cross-platform"]).optional(),
21
21
  name: z.string().optional()
22
22
  }).optional();
23
- const generatePasskeyRegistrationOptions = (opts, { maxAgeInSeconds, expirationTime }) => createAuthEndpoint("/passkey/generate-register-options", {
23
+ const generatePasskeyRegistrationOptions = (opts, { maxAgeInSeconds }) => createAuthEndpoint("/passkey/generate-register-options", {
24
24
  method: "GET",
25
25
  use: [freshSessionMiddleware],
26
26
  query: generatePasskeyQuerySchema,
@@ -134,6 +134,7 @@ const generatePasskeyRegistrationOptions = (opts, { maxAgeInSeconds, expirationT
134
134
  ...webAuthnCookie.attributes,
135
135
  maxAge: maxAgeInSeconds
136
136
  });
137
+ const expirationTime = new Date(Date.now() + maxAgeInSeconds * 1e3);
137
138
  await ctx.context.internalAdapter.createVerificationValue({
138
139
  identifier: verificationToken,
139
140
  value: JSON.stringify({
@@ -144,7 +145,7 @@ const generatePasskeyRegistrationOptions = (opts, { maxAgeInSeconds, expirationT
144
145
  });
145
146
  return ctx.json(options, { status: 200 });
146
147
  });
147
- const generatePasskeyAuthenticationOptions = (opts, { maxAgeInSeconds, expirationTime }) => createAuthEndpoint("/passkey/generate-authenticate-options", {
148
+ const generatePasskeyAuthenticationOptions = (opts, { maxAgeInSeconds }) => createAuthEndpoint("/passkey/generate-authenticate-options", {
148
149
  method: "GET",
149
150
  metadata: { openapi: {
150
151
  operationId: "passkeyGenerateAuthenticateOptions",
@@ -227,6 +228,7 @@ const generatePasskeyAuthenticationOptions = (opts, { maxAgeInSeconds, expiratio
227
228
  ...webAuthnCookie.attributes,
228
229
  maxAge: maxAgeInSeconds
229
230
  });
231
+ const expirationTime = new Date(Date.now() + maxAgeInSeconds * 1e3);
230
232
  await ctx.context.internalAdapter.createVerificationValue({
231
233
  identifier: verificationToken,
232
234
  value: JSON.stringify(data),
@@ -291,7 +293,7 @@ const verifyPasskeyRegistration = (options) => createAuthEndpoint("/passkey/veri
291
293
  model: "passkey",
292
294
  data: newPasskey
293
295
  });
294
- await ctx.context.internalAdapter.deleteVerificationValue(data.id);
296
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(verificationToken);
295
297
  return ctx.json(newPasskeyRes, { status: 200 });
296
298
  } catch (e) {
297
299
  ctx.context.logger.error("Failed to verify registration", e);
@@ -369,7 +371,7 @@ const verifyPasskeyAuthentication = (options) => createAuthEndpoint("/passkey/ve
369
371
  session: s,
370
372
  user
371
373
  });
372
- await ctx.context.internalAdapter.deleteVerificationValue(data.id);
374
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(verificationToken);
373
375
  return ctx.json({ session: s }, { status: 200 });
374
376
  } catch (e) {
375
377
  ctx.context.logger.error("Failed to verify authentication", e);
@@ -586,6 +588,7 @@ const schema = { passkey: { fields: {
586
588
 
587
589
  //#endregion
588
590
  //#region src/index.ts
591
+ const MAX_AGE_IN_SECONDS = 300;
589
592
  const passkey = (options) => {
590
593
  const opts = {
591
594
  origin: null,
@@ -595,20 +598,11 @@ const passkey = (options) => {
595
598
  ...options?.advanced
596
599
  }
597
600
  };
598
- const expirationTime = new Date(Date.now() + 1e3 * 60 * 5);
599
- const currentTime = /* @__PURE__ */ new Date();
600
- const maxAgeInSeconds = Math.floor((expirationTime.getTime() - currentTime.getTime()) / 1e3);
601
601
  return {
602
602
  id: "passkey",
603
603
  endpoints: {
604
- generatePasskeyRegistrationOptions: generatePasskeyRegistrationOptions(opts, {
605
- maxAgeInSeconds,
606
- expirationTime
607
- }),
608
- generatePasskeyAuthenticationOptions: generatePasskeyAuthenticationOptions(opts, {
609
- maxAgeInSeconds,
610
- expirationTime
611
- }),
604
+ generatePasskeyRegistrationOptions: generatePasskeyRegistrationOptions(opts, { maxAgeInSeconds: MAX_AGE_IN_SECONDS }),
605
+ generatePasskeyAuthenticationOptions: generatePasskeyAuthenticationOptions(opts, { maxAgeInSeconds: MAX_AGE_IN_SECONDS }),
612
606
  verifyPasskeyRegistration: verifyPasskeyRegistration(opts),
613
607
  verifyPasskeyAuthentication: verifyPasskeyAuthentication(opts),
614
608
  listPasskeys,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils.ts","../src/routes.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import type { PasskeyOptions } from \"./types\";\n\nexport function getRpID(options: PasskeyOptions, baseURL?: string | undefined) {\n\treturn (\n\t\toptions.rpID || (baseURL ? new URL(baseURL).hostname : \"localhost\") // default rpID\n\t);\n}\n","import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { APIError } from \"@better-auth/core/error\";\nimport { base64 } from \"@better-auth/utils/base64\";\nimport type {\n\tAuthenticationResponseJSON,\n\tAuthenticatorTransportFuture,\n} from \"@simplewebauthn/server\";\nimport {\n\tgenerateAuthenticationOptions,\n\tgenerateRegistrationOptions,\n\tverifyAuthenticationResponse,\n\tverifyRegistrationResponse,\n} from \"@simplewebauthn/server\";\nimport {\n\tfreshSessionMiddleware,\n\tgetSessionFromCtx,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport { setSessionCookie } from \"better-auth/cookies\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport * as z from \"zod\";\nimport { PASSKEY_ERROR_CODES } from \"./error-codes\";\nimport type { Passkey, PasskeyOptions, WebAuthnChallengeValue } from \"./types\";\nimport { getRpID } from \"./utils\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype RequiredPassKeyOptions = WithRequired<PasskeyOptions, \"advanced\"> & {\n\tadvanced: Required<PasskeyOptions[\"advanced\"]>;\n};\n\nconst generatePasskeyQuerySchema = z\n\t.object({\n\t\tauthenticatorAttachment: z.enum([\"platform\", \"cross-platform\"]).optional(),\n\t\tname: z.string().optional(),\n\t})\n\t.optional();\n\nexport const generatePasskeyRegistrationOptions = (\n\topts: RequiredPassKeyOptions,\n\t{\n\t\tmaxAgeInSeconds,\n\t\texpirationTime,\n\t}: { maxAgeInSeconds: number; expirationTime: Date },\n) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/generate-register-options\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [freshSessionMiddleware],\n\t\t\tquery: generatePasskeyQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"generatePasskeyRegistrationOptions\",\n\t\t\t\t\tdescription: \"Generate registration options for a new passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\tdescription: `Type of authenticator to use for registration.\n \"platform\" for device-specific authenticators,\n \"cross-platform\" for authenticators that can be used across devices.`,\n\t\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\tdescription: `Optional custom name for the passkey.\n This can help identify the passkey when managing multiple credentials.`,\n\t\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tchallenge: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trp: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplayName: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpubKeyCredParams: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talg: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttimeout: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\texcludeCredentials: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttransports: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\trequireResidentKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tattestation: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t\t\t\textensions: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { session } = ctx.context;\n\t\t\tconst userPasskeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\t\tmodel: \"passkey\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\t\tvalue: session.user.id,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tconst userID = new TextEncoder().encode(\n\t\t\t\tgenerateRandomString(32, \"a-z\", \"0-9\"),\n\t\t\t);\n\t\t\tconst options = await generateRegistrationOptions({\n\t\t\t\trpName: opts.rpName || ctx.context.appName,\n\t\t\t\trpID: getRpID(opts, ctx.context.options.baseURL),\n\t\t\t\tuserID,\n\t\t\t\tuserName: ctx.query?.name || session.user.email || session.user.id,\n\t\t\t\tuserDisplayName: session.user.email || session.user.id,\n\t\t\t\tattestationType: \"none\",\n\t\t\t\texcludeCredentials: userPasskeys.map((passkey) => ({\n\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\",\",\n\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t})),\n\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\tresidentKey: \"preferred\",\n\t\t\t\t\tuserVerification: \"preferred\",\n\t\t\t\t\t...(opts.authenticatorSelection || {}),\n\t\t\t\t\t...(ctx.query?.authenticatorAttachment\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tauthenticatorAttachment: ctx.query.authenticatorAttachment,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst verificationToken = generateRandomString(32);\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\topts.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tawait ctx.setSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tverificationToken,\n\t\t\t\tctx.context.secret,\n\t\t\t\t{\n\t\t\t\t\t...webAuthnCookie.attributes,\n\t\t\t\t\tmaxAge: maxAgeInSeconds,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tidentifier: verificationToken,\n\t\t\t\tvalue: JSON.stringify({\n\t\t\t\t\texpectedChallenge: options.challenge,\n\t\t\t\t\tuserData: {\n\t\t\t\t\t\tid: session.user.id,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\texpiresAt: expirationTime,\n\t\t\t});\n\t\t\treturn ctx.json(options, {\n\t\t\t\tstatus: 200,\n\t\t\t});\n\t\t},\n\t);\n\nexport const generatePasskeyAuthenticationOptions = (\n\topts: RequiredPassKeyOptions,\n\t{\n\t\tmaxAgeInSeconds,\n\t\texpirationTime,\n\t}: { maxAgeInSeconds: number; expirationTime: Date },\n) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/generate-authenticate-options\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyGenerateAuthenticateOptions\",\n\t\t\t\t\tdescription: \"Generate authentication options for a passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tchallenge: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trp: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplayName: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttimeout: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tallowCredentials: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttransports: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\trequireResidentKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\textensions: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tlet userPasskeys: Passkey[] = [];\n\t\t\tif (session) {\n\t\t\t\tuserPasskeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\t\t\tvalue: session.user.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst options = await generateAuthenticationOptions({\n\t\t\t\trpID: getRpID(opts, ctx.context.options.baseURL),\n\t\t\t\tuserVerification: \"preferred\",\n\t\t\t\t...(userPasskeys.length\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tallowCredentials: userPasskeys.map((passkey) => ({\n\t\t\t\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\t\t\t\",\",\n\t\t\t\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t});\n\t\t\tconst data = {\n\t\t\t\texpectedChallenge: options.challenge,\n\t\t\t\tuserData: {\n\t\t\t\t\tid: session?.user.id || \"\",\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst verificationToken = generateRandomString(32);\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\topts.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tawait ctx.setSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tverificationToken,\n\t\t\t\tctx.context.secret,\n\t\t\t\t{\n\t\t\t\t\t...webAuthnCookie.attributes,\n\t\t\t\t\tmaxAge: maxAgeInSeconds,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tidentifier: verificationToken,\n\t\t\t\tvalue: JSON.stringify(data),\n\t\t\t\texpiresAt: expirationTime,\n\t\t\t});\n\t\t\treturn ctx.json(options, {\n\t\t\t\tstatus: 200,\n\t\t\t});\n\t\t},\n\t);\n\nconst verifyPasskeyRegistrationBodySchema = z.object({\n\tresponse: z.any(),\n\tname: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Name of the passkey\",\n\t\t})\n\t\t.optional(),\n});\n\nexport const verifyPasskeyRegistration = (options: RequiredPassKeyOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/verify-registration\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyPasskeyRegistrationBodySchema,\n\t\t\tuse: [freshSessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyVerifyRegistration\",\n\t\t\t\t\tdescription: \"Verify registration of a new passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t400: {\n\t\t\t\t\t\t\tdescription: \"Bad request\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst origin = options?.origin || ctx.headers?.get(\"origin\") || \"\";\n\t\t\tif (!origin) {\n\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst resp = ctx.body.response;\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\toptions.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tconst verificationToken = await ctx.getSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tctx.context.secret,\n\t\t\t);\n\t\t\tif (!verificationToken) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst data =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\t\t\tif (!data) {\n\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { expectedChallenge, userData } = JSON.parse(\n\t\t\t\tdata.value,\n\t\t\t) as WebAuthnChallengeValue;\n\n\t\t\tif (userData.id !== ctx.context.session.user.id) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst verification = await verifyRegistrationResponse({\n\t\t\t\t\tresponse: resp,\n\t\t\t\t\texpectedChallenge,\n\t\t\t\t\texpectedOrigin: origin,\n\t\t\t\t\texpectedRPID: getRpID(options, ctx.context.options.baseURL),\n\t\t\t\t\trequireUserVerification: false,\n\t\t\t\t});\n\t\t\t\tconst { verified, registrationInfo } = verification;\n\t\t\t\tif (!verified || !registrationInfo) {\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst { aaguid, credentialDeviceType, credentialBackedUp, credential } =\n\t\t\t\t\tregistrationInfo;\n\t\t\t\tconst pubKey = base64.encode(credential.publicKey);\n\t\t\t\tconst newPasskey: Omit<Passkey, \"id\"> = {\n\t\t\t\t\tname: ctx.body.name,\n\t\t\t\t\tuserId: userData.id,\n\t\t\t\t\tcredentialID: credential.id,\n\t\t\t\t\tpublicKey: pubKey,\n\t\t\t\t\tcounter: credential.counter,\n\t\t\t\t\tdeviceType: credentialDeviceType,\n\t\t\t\t\ttransports: resp.response.transports.join(\",\"),\n\t\t\t\t\tbackedUp: credentialBackedUp,\n\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\taaguid: aaguid,\n\t\t\t\t};\n\t\t\t\tconst newPasskeyRes = await ctx.context.adapter.create<\n\t\t\t\t\tOmit<Passkey, \"id\">,\n\t\t\t\t\tPasskey\n\t\t\t\t>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\tdata: newPasskey,\n\t\t\t\t});\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(data.id);\n\t\t\t\treturn ctx.json(newPasskeyRes, {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify registration\", e);\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\nconst verifyPasskeyAuthenticationBodySchema = z.object({\n\tresponse: z.record(z.any(), z.any()),\n});\n\nexport const verifyPasskeyAuthentication = (options: RequiredPassKeyOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/verify-authentication\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyPasskeyAuthenticationBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyVerifyAuthentication\",\n\t\t\t\t\tdescription: \"Verify authentication of a passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\tresponse: AuthenticationResponseJSON;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst origin = options?.origin || ctx.headers?.get(\"origin\") || \"\";\n\t\t\tif (!origin) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"origin missing\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst resp = ctx.body.response;\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\toptions.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tconst verificationToken = await ctx.getSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tctx.context.secret,\n\t\t\t);\n\t\t\tif (!verificationToken) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst data =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\t\t\tif (!data) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { expectedChallenge } = JSON.parse(\n\t\t\t\tdata.value,\n\t\t\t) as WebAuthnChallengeValue;\n\t\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\t\tmodel: \"passkey\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"credentialID\",\n\t\t\t\t\t\tvalue: resp.id,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tif (!passkey) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst verification = await verifyAuthenticationResponse({\n\t\t\t\t\tresponse: resp as AuthenticationResponseJSON,\n\t\t\t\t\texpectedChallenge,\n\t\t\t\t\texpectedOrigin: origin,\n\t\t\t\t\texpectedRPID: getRpID(options, ctx.context.options.baseURL),\n\t\t\t\t\tcredential: {\n\t\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\t\tpublicKey: base64.decode(passkey.publicKey),\n\t\t\t\t\t\tcounter: passkey.counter,\n\t\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\t\",\",\n\t\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t\t},\n\t\t\t\t\trequireUserVerification: false,\n\t\t\t\t});\n\t\t\t\tconst { verified } = verification;\n\t\t\t\tif (!verified)\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.AUTHENTICATION_FAILED,\n\t\t\t\t\t);\n\n\t\t\t\tawait ctx.context.adapter.update<Passkey>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\tvalue: passkey.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tcounter: verification.authenticationInfo.newCounter,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tconst s = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tpasskey.userId,\n\t\t\t\t);\n\t\t\t\tif (!s) {\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.UNABLE_TO_CREATE_SESSION,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst user = await ctx.context.internalAdapter.findUserById(\n\t\t\t\t\tpasskey.userId,\n\t\t\t\t);\n\t\t\t\tif (!user) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"User not found\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession: s,\n\t\t\t\t\tuser,\n\t\t\t\t});\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(data.id);\n\n\t\t\t\treturn ctx.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tsession: s,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify authentication\", e);\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.AUTHENTICATION_FAILED,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\n/**\n * ### Endpoint\n *\n * GET `/passkey/list-user-passkeys`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.listPasskeys`\n *\n * **client:**\n * `authClient.passkey.listUserPasskeys`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-list-user-passkeys)\n */\nexport const listPasskeys = createAuthEndpoint(\n\t\"/passkey/list-user-passkeys\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"List all passkeys for the authenticated user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkeys retrieved successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t\trequired: [\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"userId\",\n\t\t\t\t\t\t\t\t\t\t\t\"publicKey\",\n\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\"Array of passkey objects associated with the user\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [{ field: \"userId\", value: ctx.context.session.user.id }],\n\t\t});\n\t\treturn ctx.json(passkeys, {\n\t\t\tstatus: 200,\n\t\t});\n\t},\n);\n\nconst deletePasskeyBodySchema = z.object({\n\tid: z.string().meta({\n\t\tdescription: 'The ID of the passkey to delete. Eg: \"some-passkey-id\"',\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/passkey/delete-passkey`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.deletePasskey`\n *\n * **client:**\n * `authClient.passkey.deletePasskey`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-delete-passkey)\n */\nexport const deletePasskey = createAuthEndpoint(\n\t\"/passkey/delete-passkey\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: deletePasskeyBodySchema,\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Delete a specific passkey\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkey deleted successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates whether the deletion was successful\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tif (!passkey) {\n\t\t\tthrow APIError.from(\"NOT_FOUND\", PASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND);\n\t\t}\n\t\tif (passkey.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\tawait ctx.context.adapter.delete({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [{ field: \"id\", value: passkey.id }],\n\t\t});\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nconst updatePassKeyBodySchema = z.object({\n\tid: z.string().meta({\n\t\tdescription: `The ID of the passkey which will be updated. Eg: \\\"passkey-id\\\"`,\n\t}),\n\tname: z.string().meta({\n\t\tdescription: `The new name which the passkey will be updated to. Eg: \\\"my-new-passkey-name\\\"`,\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/passkey/update-passkey`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.updatePasskey`\n *\n * **client:**\n * `authClient.passkey.updatePasskey`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-update-passkey)\n */\nexport const updatePasskey = createAuthEndpoint(\n\t\"/passkey/update-passkey\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: updatePassKeyBodySchema,\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Update a specific passkey's name\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkey updated successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tpasskey: {\n\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"passkey\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tif (!passkey) {\n\t\t\tthrow APIError.from(\"NOT_FOUND\", PASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND);\n\t\t}\n\n\t\tif (passkey.userId !== ctx.context.session.user.id) {\n\t\t\tthrow APIError.from(\n\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\tPASSKEY_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY,\n\t\t\t);\n\t\t}\n\n\t\tconst updatedPasskey = await ctx.context.adapter.update<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: {\n\t\t\t\tname: ctx.body.name,\n\t\t\t},\n\t\t});\n\n\t\tif (!updatedPasskey) {\n\t\t\tthrow APIError.from(\n\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_UPDATE_PASSKEY,\n\t\t\t);\n\t\t}\n\t\treturn ctx.json(\n\t\t\t{\n\t\t\t\tpasskey: updatedPasskey,\n\t\t\t},\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t},\n\t\t);\n\t},\n);\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\n\nexport const schema = {\n\tpasskey: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tcredentialID: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tcounter: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdeviceType: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tbackedUp: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\ttransports: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\taaguid: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n","import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { mergeSchema } from \"better-auth/db\";\nimport { PASSKEY_ERROR_CODES } from \"./error-codes\";\nimport {\n\tdeletePasskey,\n\tgeneratePasskeyAuthenticationOptions,\n\tgeneratePasskeyRegistrationOptions,\n\tlistPasskeys,\n\tupdatePasskey,\n\tverifyPasskeyAuthentication,\n\tverifyPasskeyRegistration,\n} from \"./routes\";\nimport { schema } from \"./schema\";\nimport type { Passkey, PasskeyOptions } from \"./types\";\n\ndeclare module \"@better-auth/core\" {\n\tinterface BetterAuthPluginRegistry<AuthOptions, Options> {\n\t\tpasskey: {\n\t\t\tcreator: typeof passkey;\n\t\t};\n\t}\n}\n\nexport const passkey = (options?: PasskeyOptions | undefined) => {\n\tconst opts = {\n\t\torigin: null,\n\t\t...options,\n\t\tadvanced: {\n\t\t\twebAuthnChallengeCookie: \"better-auth-passkey\",\n\t\t\t...options?.advanced,\n\t\t},\n\t};\n\tconst expirationTime = new Date(Date.now() + 1000 * 60 * 5);\n\tconst currentTime = new Date();\n\tconst maxAgeInSeconds = Math.floor(\n\t\t(expirationTime.getTime() - currentTime.getTime()) / 1000,\n\t);\n\n\treturn {\n\t\tid: \"passkey\",\n\t\tendpoints: {\n\t\t\tgeneratePasskeyRegistrationOptions: generatePasskeyRegistrationOptions(\n\t\t\t\topts,\n\t\t\t\t{ maxAgeInSeconds, expirationTime },\n\t\t\t),\n\t\t\tgeneratePasskeyAuthenticationOptions:\n\t\t\t\tgeneratePasskeyAuthenticationOptions(opts, {\n\t\t\t\t\tmaxAgeInSeconds,\n\t\t\t\t\texpirationTime,\n\t\t\t\t}),\n\t\t\tverifyPasskeyRegistration: verifyPasskeyRegistration(opts),\n\t\t\tverifyPasskeyAuthentication: verifyPasskeyAuthentication(opts),\n\t\t\tlistPasskeys,\n\t\t\tdeletePasskey,\n\t\t\tupdatePasskey,\n\t\t},\n\t\tschema: mergeSchema(schema, options?.schema),\n\t\t$ERROR_CODES: PASSKEY_ERROR_CODES,\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport type { Passkey, PasskeyOptions };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils.ts","../src/routes.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import type { PasskeyOptions } from \"./types\";\n\nexport function getRpID(options: PasskeyOptions, baseURL?: string | undefined) {\n\treturn (\n\t\toptions.rpID || (baseURL ? new URL(baseURL).hostname : \"localhost\") // default rpID\n\t);\n}\n","import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { APIError } from \"@better-auth/core/error\";\nimport { base64 } from \"@better-auth/utils/base64\";\nimport type {\n\tAuthenticationResponseJSON,\n\tAuthenticatorTransportFuture,\n} from \"@simplewebauthn/server\";\nimport {\n\tgenerateAuthenticationOptions,\n\tgenerateRegistrationOptions,\n\tverifyAuthenticationResponse,\n\tverifyRegistrationResponse,\n} from \"@simplewebauthn/server\";\nimport {\n\tfreshSessionMiddleware,\n\tgetSessionFromCtx,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport { setSessionCookie } from \"better-auth/cookies\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport * as z from \"zod\";\nimport { PASSKEY_ERROR_CODES } from \"./error-codes\";\nimport type { Passkey, PasskeyOptions, WebAuthnChallengeValue } from \"./types\";\nimport { getRpID } from \"./utils\";\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\ntype RequiredPassKeyOptions = WithRequired<PasskeyOptions, \"advanced\"> & {\n\tadvanced: Required<PasskeyOptions[\"advanced\"]>;\n};\n\nconst generatePasskeyQuerySchema = z\n\t.object({\n\t\tauthenticatorAttachment: z.enum([\"platform\", \"cross-platform\"]).optional(),\n\t\tname: z.string().optional(),\n\t})\n\t.optional();\n\nexport const generatePasskeyRegistrationOptions = (\n\topts: RequiredPassKeyOptions,\n\t{ maxAgeInSeconds }: { maxAgeInSeconds: number },\n) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/generate-register-options\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [freshSessionMiddleware],\n\t\t\tquery: generatePasskeyQuerySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"generatePasskeyRegistrationOptions\",\n\t\t\t\t\tdescription: \"Generate registration options for a new passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\tdescription: `Type of authenticator to use for registration.\n \"platform\" for device-specific authenticators,\n \"cross-platform\" for authenticators that can be used across devices.`,\n\t\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\tdescription: `Optional custom name for the passkey.\n This can help identify the passkey when managing multiple credentials.`,\n\t\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tchallenge: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trp: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplayName: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpubKeyCredParams: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talg: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttimeout: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\texcludeCredentials: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttransports: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\trequireResidentKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tattestation: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t\t\t\textensions: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { session } = ctx.context;\n\t\t\tconst userPasskeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\t\tmodel: \"passkey\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\t\tvalue: session.user.id,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tconst userID = new TextEncoder().encode(\n\t\t\t\tgenerateRandomString(32, \"a-z\", \"0-9\"),\n\t\t\t);\n\t\t\tconst options = await generateRegistrationOptions({\n\t\t\t\trpName: opts.rpName || ctx.context.appName,\n\t\t\t\trpID: getRpID(opts, ctx.context.options.baseURL),\n\t\t\t\tuserID,\n\t\t\t\tuserName: ctx.query?.name || session.user.email || session.user.id,\n\t\t\t\tuserDisplayName: session.user.email || session.user.id,\n\t\t\t\tattestationType: \"none\",\n\t\t\t\texcludeCredentials: userPasskeys.map((passkey) => ({\n\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\",\",\n\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t})),\n\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\tresidentKey: \"preferred\",\n\t\t\t\t\tuserVerification: \"preferred\",\n\t\t\t\t\t...(opts.authenticatorSelection || {}),\n\t\t\t\t\t...(ctx.query?.authenticatorAttachment\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tauthenticatorAttachment: ctx.query.authenticatorAttachment,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst verificationToken = generateRandomString(32);\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\topts.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tawait ctx.setSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tverificationToken,\n\t\t\t\tctx.context.secret,\n\t\t\t\t{\n\t\t\t\t\t...webAuthnCookie.attributes,\n\t\t\t\t\tmaxAge: maxAgeInSeconds,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst expirationTime = new Date(Date.now() + maxAgeInSeconds * 1000);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tidentifier: verificationToken,\n\t\t\t\tvalue: JSON.stringify({\n\t\t\t\t\texpectedChallenge: options.challenge,\n\t\t\t\t\tuserData: {\n\t\t\t\t\t\tid: session.user.id,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\texpiresAt: expirationTime,\n\t\t\t});\n\t\t\treturn ctx.json(options, {\n\t\t\t\tstatus: 200,\n\t\t\t});\n\t\t},\n\t);\n\nexport const generatePasskeyAuthenticationOptions = (\n\topts: RequiredPassKeyOptions,\n\t{ maxAgeInSeconds }: { maxAgeInSeconds: number },\n) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/generate-authenticate-options\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyGenerateAuthenticateOptions\",\n\t\t\t\t\tdescription: \"Generate authentication options for a passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tchallenge: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trp: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplayName: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttimeout: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tallowCredentials: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttransports: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tauthenticatorAttachment: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\trequireResidentKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tuserVerification: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\textensions: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tlet userPasskeys: Passkey[] = [];\n\t\t\tif (session) {\n\t\t\t\tuserPasskeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\t\t\tvalue: session.user.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst options = await generateAuthenticationOptions({\n\t\t\t\trpID: getRpID(opts, ctx.context.options.baseURL),\n\t\t\t\tuserVerification: \"preferred\",\n\t\t\t\t...(userPasskeys.length\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tallowCredentials: userPasskeys.map((passkey) => ({\n\t\t\t\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\t\t\t\",\",\n\t\t\t\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t});\n\t\t\tconst data = {\n\t\t\t\texpectedChallenge: options.challenge,\n\t\t\t\tuserData: {\n\t\t\t\t\tid: session?.user.id || \"\",\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst verificationToken = generateRandomString(32);\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\topts.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tawait ctx.setSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tverificationToken,\n\t\t\t\tctx.context.secret,\n\t\t\t\t{\n\t\t\t\t\t...webAuthnCookie.attributes,\n\t\t\t\t\tmaxAge: maxAgeInSeconds,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst expirationTime = new Date(Date.now() + maxAgeInSeconds * 1000);\n\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\tidentifier: verificationToken,\n\t\t\t\tvalue: JSON.stringify(data),\n\t\t\t\texpiresAt: expirationTime,\n\t\t\t});\n\t\t\treturn ctx.json(options, {\n\t\t\t\tstatus: 200,\n\t\t\t});\n\t\t},\n\t);\n\nconst verifyPasskeyRegistrationBodySchema = z.object({\n\tresponse: z.any(),\n\tname: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Name of the passkey\",\n\t\t})\n\t\t.optional(),\n});\n\nexport const verifyPasskeyRegistration = (options: RequiredPassKeyOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/verify-registration\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyPasskeyRegistrationBodySchema,\n\t\t\tuse: [freshSessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyVerifyRegistration\",\n\t\t\t\t\tdescription: \"Verify registration of a new passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t400: {\n\t\t\t\t\t\t\tdescription: \"Bad request\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst origin = options?.origin || ctx.headers?.get(\"origin\") || \"\";\n\t\t\tif (!origin) {\n\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst resp = ctx.body.response;\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\toptions.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tconst verificationToken = await ctx.getSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tctx.context.secret,\n\t\t\t);\n\t\t\tif (!verificationToken) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst data =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\t\t\tif (!data) {\n\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { expectedChallenge, userData } = JSON.parse(\n\t\t\t\tdata.value,\n\t\t\t) as WebAuthnChallengeValue;\n\n\t\t\tif (userData.id !== ctx.context.session.user.id) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst verification = await verifyRegistrationResponse({\n\t\t\t\t\tresponse: resp,\n\t\t\t\t\texpectedChallenge,\n\t\t\t\t\texpectedOrigin: origin,\n\t\t\t\t\texpectedRPID: getRpID(options, ctx.context.options.baseURL),\n\t\t\t\t\trequireUserVerification: false,\n\t\t\t\t});\n\t\t\t\tconst { verified, registrationInfo } = verification;\n\t\t\t\tif (!verified || !registrationInfo) {\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst { aaguid, credentialDeviceType, credentialBackedUp, credential } =\n\t\t\t\t\tregistrationInfo;\n\t\t\t\tconst pubKey = base64.encode(credential.publicKey);\n\t\t\t\tconst newPasskey: Omit<Passkey, \"id\"> = {\n\t\t\t\t\tname: ctx.body.name,\n\t\t\t\t\tuserId: userData.id,\n\t\t\t\t\tcredentialID: credential.id,\n\t\t\t\t\tpublicKey: pubKey,\n\t\t\t\t\tcounter: credential.counter,\n\t\t\t\t\tdeviceType: credentialDeviceType,\n\t\t\t\t\ttransports: resp.response.transports.join(\",\"),\n\t\t\t\t\tbackedUp: credentialBackedUp,\n\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\taaguid: aaguid,\n\t\t\t\t};\n\t\t\t\tconst newPasskeyRes = await ctx.context.adapter.create<\n\t\t\t\t\tOmit<Passkey, \"id\">,\n\t\t\t\t\tPasskey\n\t\t\t\t>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\tdata: newPasskey,\n\t\t\t\t});\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\t\t\t\treturn ctx.json(newPasskeyRes, {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify registration\", e);\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\nconst verifyPasskeyAuthenticationBodySchema = z.object({\n\tresponse: z.record(z.any(), z.any()),\n});\n\nexport const verifyPasskeyAuthentication = (options: RequiredPassKeyOptions) =>\n\tcreateAuthEndpoint(\n\t\t\"/passkey/verify-authentication\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyPasskeyAuthenticationBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"passkeyVerifyAuthentication\",\n\t\t\t\t\tdescription: \"Verify authentication of a passkey\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\tresponse: AuthenticationResponseJSON;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst origin = options?.origin || ctx.headers?.get(\"origin\") || \"\";\n\t\t\tif (!origin) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"origin missing\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst resp = ctx.body.response;\n\t\t\tconst webAuthnCookie = ctx.context.createAuthCookie(\n\t\t\t\toptions.advanced.webAuthnChallengeCookie,\n\t\t\t);\n\t\t\tconst verificationToken = await ctx.getSignedCookie(\n\t\t\t\twebAuthnCookie.name,\n\t\t\t\tctx.context.secret,\n\t\t\t);\n\t\t\tif (!verificationToken) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst data =\n\t\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\t\t\tif (!data) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.CHALLENGE_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { expectedChallenge } = JSON.parse(\n\t\t\t\tdata.value,\n\t\t\t) as WebAuthnChallengeValue;\n\t\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\t\tmodel: \"passkey\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"credentialID\",\n\t\t\t\t\t\tvalue: resp.id,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tif (!passkey) {\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst verification = await verifyAuthenticationResponse({\n\t\t\t\t\tresponse: resp as AuthenticationResponseJSON,\n\t\t\t\t\texpectedChallenge,\n\t\t\t\t\texpectedOrigin: origin,\n\t\t\t\t\texpectedRPID: getRpID(options, ctx.context.options.baseURL),\n\t\t\t\t\tcredential: {\n\t\t\t\t\t\tid: passkey.credentialID,\n\t\t\t\t\t\tpublicKey: base64.decode(passkey.publicKey),\n\t\t\t\t\t\tcounter: passkey.counter,\n\t\t\t\t\t\ttransports: passkey.transports?.split(\n\t\t\t\t\t\t\t\",\",\n\t\t\t\t\t\t) as AuthenticatorTransportFuture[],\n\t\t\t\t\t},\n\t\t\t\t\trequireUserVerification: false,\n\t\t\t\t});\n\t\t\t\tconst { verified } = verification;\n\t\t\t\tif (!verified)\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.AUTHENTICATION_FAILED,\n\t\t\t\t\t);\n\n\t\t\t\tawait ctx.context.adapter.update<Passkey>({\n\t\t\t\t\tmodel: \"passkey\",\n\t\t\t\t\twhere: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\tvalue: passkey.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tcounter: verification.authenticationInfo.newCounter,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tconst s = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tpasskey.userId,\n\t\t\t\t);\n\t\t\t\tif (!s) {\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.UNABLE_TO_CREATE_SESSION,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst user = await ctx.context.internalAdapter.findUserById(\n\t\t\t\t\tpasskey.userId,\n\t\t\t\t);\n\t\t\t\tif (!user) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"User not found\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession: s,\n\t\t\t\t\tuser,\n\t\t\t\t});\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationByIdentifier(\n\t\t\t\t\tverificationToken,\n\t\t\t\t);\n\n\t\t\t\treturn ctx.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tsession: s,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify authentication\", e);\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.AUTHENTICATION_FAILED,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\n/**\n * ### Endpoint\n *\n * GET `/passkey/list-user-passkeys`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.listPasskeys`\n *\n * **client:**\n * `authClient.passkey.listUserPasskeys`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-list-user-passkeys)\n */\nexport const listPasskeys = createAuthEndpoint(\n\t\"/passkey/list-user-passkeys\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"List all passkeys for the authenticated user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkeys retrieved successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t\trequired: [\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"userId\",\n\t\t\t\t\t\t\t\t\t\t\t\"publicKey\",\n\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\"Array of passkey objects associated with the user\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkeys = await ctx.context.adapter.findMany<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [{ field: \"userId\", value: ctx.context.session.user.id }],\n\t\t});\n\t\treturn ctx.json(passkeys, {\n\t\t\tstatus: 200,\n\t\t});\n\t},\n);\n\nconst deletePasskeyBodySchema = z.object({\n\tid: z.string().meta({\n\t\tdescription: 'The ID of the passkey to delete. Eg: \"some-passkey-id\"',\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/passkey/delete-passkey`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.deletePasskey`\n *\n * **client:**\n * `authClient.passkey.deletePasskey`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-delete-passkey)\n */\nexport const deletePasskey = createAuthEndpoint(\n\t\"/passkey/delete-passkey\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: deletePasskeyBodySchema,\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Delete a specific passkey\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkey deleted successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates whether the deletion was successful\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tif (!passkey) {\n\t\t\tthrow APIError.from(\"NOT_FOUND\", PASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND);\n\t\t}\n\t\tif (passkey.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\tawait ctx.context.adapter.delete({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [{ field: \"id\", value: passkey.id }],\n\t\t});\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nconst updatePassKeyBodySchema = z.object({\n\tid: z.string().meta({\n\t\tdescription: `The ID of the passkey which will be updated. Eg: \\\"passkey-id\\\"`,\n\t}),\n\tname: z.string().meta({\n\t\tdescription: `The new name which the passkey will be updated to. Eg: \\\"my-new-passkey-name\\\"`,\n\t}),\n});\n\n/**\n * ### Endpoint\n *\n * POST `/passkey/update-passkey`\n *\n * ### API Methods\n *\n * **server:**\n * `auth.api.updatePasskey`\n *\n * **client:**\n * `authClient.passkey.updatePasskey`\n *\n * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-update-passkey)\n */\nexport const updatePasskey = createAuthEndpoint(\n\t\"/passkey/update-passkey\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: updatePassKeyBodySchema,\n\t\tuse: [sessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Update a specific passkey's name\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Passkey updated successfully\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tpasskey: {\n\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Passkey\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"passkey\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\tasync (ctx) => {\n\t\tconst passkey = await ctx.context.adapter.findOne<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tif (!passkey) {\n\t\t\tthrow APIError.from(\"NOT_FOUND\", PASSKEY_ERROR_CODES.PASSKEY_NOT_FOUND);\n\t\t}\n\n\t\tif (passkey.userId !== ctx.context.session.user.id) {\n\t\t\tthrow APIError.from(\n\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\tPASSKEY_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY,\n\t\t\t);\n\t\t}\n\n\t\tconst updatedPasskey = await ctx.context.adapter.update<Passkey>({\n\t\t\tmodel: \"passkey\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: ctx.body.id,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: {\n\t\t\t\tname: ctx.body.name,\n\t\t\t},\n\t\t});\n\n\t\tif (!updatedPasskey) {\n\t\t\tthrow APIError.from(\n\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_UPDATE_PASSKEY,\n\t\t\t);\n\t\t}\n\t\treturn ctx.json(\n\t\t\t{\n\t\t\t\tpasskey: updatedPasskey,\n\t\t\t},\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t},\n\t\t);\n\t},\n);\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\n\nexport const schema = {\n\tpasskey: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpublicKey: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tcredentialID: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tcounter: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdeviceType: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tbackedUp: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\ttransports: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\taaguid: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n","import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { mergeSchema } from \"better-auth/db\";\nimport { PASSKEY_ERROR_CODES } from \"./error-codes\";\nimport {\n\tdeletePasskey,\n\tgeneratePasskeyAuthenticationOptions,\n\tgeneratePasskeyRegistrationOptions,\n\tlistPasskeys,\n\tupdatePasskey,\n\tverifyPasskeyAuthentication,\n\tverifyPasskeyRegistration,\n} from \"./routes\";\nimport { schema } from \"./schema\";\nimport type { Passkey, PasskeyOptions } from \"./types\";\n\ndeclare module \"@better-auth/core\" {\n\tinterface BetterAuthPluginRegistry<AuthOptions, Options> {\n\t\tpasskey: {\n\t\t\tcreator: typeof passkey;\n\t\t};\n\t}\n}\n\nconst MAX_AGE_IN_SECONDS = 60 * 5; // 5 minutes\n\nexport const passkey = (options?: PasskeyOptions | undefined) => {\n\tconst opts = {\n\t\torigin: null,\n\t\t...options,\n\t\tadvanced: {\n\t\t\twebAuthnChallengeCookie: \"better-auth-passkey\",\n\t\t\t...options?.advanced,\n\t\t},\n\t};\n\n\treturn {\n\t\tid: \"passkey\",\n\t\tendpoints: {\n\t\t\tgeneratePasskeyRegistrationOptions: generatePasskeyRegistrationOptions(\n\t\t\t\topts,\n\t\t\t\t{ maxAgeInSeconds: MAX_AGE_IN_SECONDS },\n\t\t\t),\n\t\t\tgeneratePasskeyAuthenticationOptions:\n\t\t\t\tgeneratePasskeyAuthenticationOptions(opts, {\n\t\t\t\t\tmaxAgeInSeconds: MAX_AGE_IN_SECONDS,\n\t\t\t\t}),\n\t\t\tverifyPasskeyRegistration: verifyPasskeyRegistration(opts),\n\t\t\tverifyPasskeyAuthentication: verifyPasskeyAuthentication(opts),\n\t\t\tlistPasskeys,\n\t\t\tdeletePasskey,\n\t\t\tupdatePasskey,\n\t\t},\n\t\tschema: mergeSchema(schema, options?.schema),\n\t\t$ERROR_CODES: PASSKEY_ERROR_CODES,\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport type { Passkey, PasskeyOptions };\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/passkey",
3
- "version": "1.5.0-beta.11",
3
+ "version": "1.5.0-beta.13",
4
4
  "type": "module",
5
5
  "description": "Passkey plugin for Better Auth",
6
6
  "main": "dist/index.mjs",
@@ -33,8 +33,8 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "tsdown": "^0.20.1",
36
- "@better-auth/core": "1.5.0-beta.11",
37
- "better-auth": "1.5.0-beta.11"
36
+ "@better-auth/core": "1.5.0-beta.13",
37
+ "better-auth": "1.5.0-beta.13"
38
38
  },
39
39
  "dependencies": {
40
40
  "@simplewebauthn/browser": "^13.2.2",
@@ -44,10 +44,10 @@
44
44
  "peerDependencies": {
45
45
  "@better-auth/utils": "0.3.1",
46
46
  "@better-fetch/fetch": "1.1.21",
47
- "better-call": "1.2.0",
47
+ "better-call": "1.2.1",
48
48
  "nanostores": "^1.0.1",
49
- "@better-auth/core": "1.5.0-beta.11",
50
- "better-auth": "1.5.0-beta.11"
49
+ "@better-auth/core": "1.5.0-beta.13",
50
+ "better-auth": "1.5.0-beta.13"
51
51
  },
52
52
  "files": [
53
53
  "dist"