@better-auth/passkey 1.5.0-beta.16 → 1.5.0-beta.17
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.mjs +5 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -110,9 +110,10 @@ const generatePasskeyRegistrationOptions = (opts, { maxAgeInSeconds }) => create
|
|
|
110
110
|
}]
|
|
111
111
|
});
|
|
112
112
|
const userID = new TextEncoder().encode(generateRandomString(32, "a-z", "0-9"));
|
|
113
|
+
const baseURLString = typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : void 0;
|
|
113
114
|
const options = await generateRegistrationOptions({
|
|
114
115
|
rpName: opts.rpName || ctx.context.appName,
|
|
115
|
-
rpID: getRpID(opts,
|
|
116
|
+
rpID: getRpID(opts, baseURLString),
|
|
116
117
|
userID,
|
|
117
118
|
userName: ctx.query?.name || session.user.email || session.user.id,
|
|
118
119
|
userDisplayName: session.user.email || session.user.id,
|
|
@@ -211,7 +212,7 @@ const generatePasskeyAuthenticationOptions = (opts, { maxAgeInSeconds }) => crea
|
|
|
211
212
|
}]
|
|
212
213
|
});
|
|
213
214
|
const options = await generateAuthenticationOptions({
|
|
214
|
-
rpID: getRpID(opts, ctx.context.options.baseURL),
|
|
215
|
+
rpID: getRpID(opts, typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : void 0),
|
|
215
216
|
userVerification: "preferred",
|
|
216
217
|
...userPasskeys.length ? { allowCredentials: userPasskeys.map((passkey) => ({
|
|
217
218
|
id: passkey.credentialID,
|
|
@@ -271,7 +272,7 @@ const verifyPasskeyRegistration = (options) => createAuthEndpoint("/passkey/veri
|
|
|
271
272
|
response: resp,
|
|
272
273
|
expectedChallenge,
|
|
273
274
|
expectedOrigin: origin,
|
|
274
|
-
expectedRPID: getRpID(options, ctx.context.options.baseURL),
|
|
275
|
+
expectedRPID: getRpID(options, typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : void 0),
|
|
275
276
|
requireUserVerification: false
|
|
276
277
|
});
|
|
277
278
|
if (!verified || !registrationInfo) throw APIError.from("BAD_REQUEST", PASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION);
|
|
@@ -344,7 +345,7 @@ const verifyPasskeyAuthentication = (options) => createAuthEndpoint("/passkey/ve
|
|
|
344
345
|
response: resp,
|
|
345
346
|
expectedChallenge,
|
|
346
347
|
expectedOrigin: origin,
|
|
347
|
-
expectedRPID: getRpID(options, ctx.context.options.baseURL),
|
|
348
|
+
expectedRPID: getRpID(options, typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : void 0),
|
|
348
349
|
credential: {
|
|
349
350
|
id: passkey.credentialID,
|
|
350
351
|
publicKey: base64.decode(passkey.publicKey),
|
package/dist/index.mjs.map
CHANGED
|
@@ -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{ 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\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\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, 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\tthrow APIError.from(\n\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\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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"}
|
|
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 baseURLString =\n\t\t\t\ttypeof ctx.context.options.baseURL === \"string\"\n\t\t\t\t\t? ctx.context.options.baseURL\n\t\t\t\t\t: undefined;\n\t\t\tconst options = await generateRegistrationOptions({\n\t\t\t\trpName: opts.rpName || ctx.context.appName,\n\t\t\t\trpID: getRpID(opts, baseURLString),\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 baseURLString =\n\t\t\t\ttypeof ctx.context.options.baseURL === \"string\"\n\t\t\t\t\t? ctx.context.options.baseURL\n\t\t\t\t\t: undefined;\n\t\t\tconst options = await generateAuthenticationOptions({\n\t\t\t\trpID: getRpID(opts, baseURLString),\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\tthrow APIError.from(\n\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\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, 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 verifyBaseURL =\n\t\t\t\t\ttypeof ctx.context.options.baseURL === \"string\"\n\t\t\t\t\t\t? ctx.context.options.baseURL\n\t\t\t\t\t\t: undefined;\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, verifyBaseURL),\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\tthrow APIError.from(\n\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\tPASSKEY_ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION,\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 authBaseURL =\n\t\t\t\t\ttypeof ctx.context.options.baseURL === \"string\"\n\t\t\t\t\t\t? ctx.context.options.baseURL\n\t\t\t\t\t\t: undefined;\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, authBaseURL),\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.
|
|
3
|
+
"version": "1.5.0-beta.17",
|
|
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.3",
|
|
36
|
-
"@better-auth/core": "1.5.0-beta.
|
|
37
|
-
"better-auth": "1.5.0-beta.
|
|
36
|
+
"@better-auth/core": "1.5.0-beta.17",
|
|
37
|
+
"better-auth": "1.5.0-beta.17"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@simplewebauthn/browser": "^13.2.2",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@better-fetch/fetch": "1.1.21",
|
|
47
47
|
"better-call": "1.3.2",
|
|
48
48
|
"nanostores": "^1.0.1",
|
|
49
|
-
"@better-auth/core": "1.5.0-beta.
|
|
50
|
-
"better-auth": "1.5.0-beta.
|
|
49
|
+
"@better-auth/core": "1.5.0-beta.17",
|
|
50
|
+
"better-auth": "1.5.0-beta.17"
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"dist"
|