@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 +1 -1
- package/dist/{index-YkeSH-Ft.d.mts → index-BQvTl2Qj.d.mts} +19 -19
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +9 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
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-
|
|
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
|
|
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
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
|
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
|
-
},
|
|
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
|
|
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
|
-
},
|
|
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
|
|
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
|
-
},
|
|
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
|
|
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:
|
|
697
|
-
YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY:
|
|
698
|
-
FAILED_TO_VERIFY_REGISTRATION:
|
|
699
|
-
PASSKEY_NOT_FOUND:
|
|
700
|
-
AUTHENTICATION_FAILED:
|
|
701
|
-
UNABLE_TO_CREATE_SESSION:
|
|
702
|
-
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-
|
|
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-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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,
|
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{\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.
|
|
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.
|
|
37
|
-
"better-auth": "1.5.0-beta.
|
|
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.
|
|
47
|
+
"better-call": "1.2.1",
|
|
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.13",
|
|
50
|
+
"better-auth": "1.5.0-beta.13"
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"dist"
|