faire-auth 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/dist/{adapter-factory-lKIOf2OR.mjs → adapter-factory-qPVW8x9-.mjs} +34 -36
  2. package/dist/{adapter-factory-D1I7joki.cjs → adapter-factory-u8r3oTez.cjs} +66 -68
  3. package/dist/adapters/drizzle-adapter/index.cjs +34 -40
  4. package/dist/adapters/drizzle-adapter/index.d.cts +4 -9
  5. package/dist/adapters/drizzle-adapter/index.d.mts +4 -9
  6. package/dist/adapters/drizzle-adapter/index.mjs +20 -26
  7. package/dist/adapters/index.cjs +11 -16
  8. package/dist/adapters/index.d.cts +11 -37
  9. package/dist/adapters/index.d.mts +11 -37
  10. package/dist/adapters/index.mjs +4 -13
  11. package/dist/adapters/kysely-adapter/index.cjs +270 -11
  12. package/dist/adapters/kysely-adapter/index.d.cts +9 -19
  13. package/dist/adapters/kysely-adapter/index.d.mts +9 -19
  14. package/dist/adapters/kysely-adapter/index.mjs +267 -9
  15. package/dist/adapters/memory-adapter/index.cjs +146 -9
  16. package/dist/adapters/memory-adapter/index.d.cts +4 -10
  17. package/dist/adapters/memory-adapter/index.d.mts +4 -10
  18. package/dist/adapters/memory-adapter/index.mjs +145 -9
  19. package/dist/adapters/mongodb-adapter/index.cjs +13 -21
  20. package/dist/adapters/mongodb-adapter/index.d.cts +3 -8
  21. package/dist/adapters/mongodb-adapter/index.d.mts +4 -9
  22. package/dist/adapters/mongodb-adapter/index.mjs +12 -20
  23. package/dist/adapters/prisma-adapter/index.cjs +12 -20
  24. package/dist/adapters/prisma-adapter/index.d.cts +4 -8
  25. package/dist/adapters/prisma-adapter/index.d.mts +4 -8
  26. package/dist/adapters/prisma-adapter/index.mjs +5 -13
  27. package/dist/adapters/test.cjs +86 -69
  28. package/dist/adapters/test.d.cts +7 -11
  29. package/dist/adapters/test.d.mts +7 -11
  30. package/dist/adapters/test.mjs +83 -66
  31. package/dist/api/index.cjs +3 -20
  32. package/dist/api/index.d.cts +2 -3
  33. package/dist/api/index.d.mts +2 -3
  34. package/dist/api/index.mjs +1 -20
  35. package/dist/api/middleware/index.cjs +4 -11
  36. package/dist/api/middleware/index.d.cts +3 -9
  37. package/dist/api/middleware/index.d.mts +3 -9
  38. package/dist/api/middleware/index.mjs +3 -11
  39. package/dist/{api-B4RDwBty.mjs → api-0f-F-Fi2.mjs} +292 -189
  40. package/dist/{api-CaRC1Gio.cjs → api-LjfH6hQi.cjs} +557 -452
  41. package/dist/{test-utils/bun-sqlite-dialect-BZBvHchL.cjs → bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
  42. package/dist/{test-utils/bun-sqlite-dialect-BSWhhKNs.mjs → bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
  43. package/dist/client/index.cjs +8 -15
  44. package/dist/client/index.d.cts +9 -14
  45. package/dist/client/index.d.mts +9 -14
  46. package/dist/client/index.mjs +7 -15
  47. package/dist/client/lynx/index.cjs +10 -18
  48. package/dist/client/lynx/index.d.cts +402 -71
  49. package/dist/client/lynx/index.d.mts +402 -71
  50. package/dist/client/lynx/index.mjs +5 -13
  51. package/dist/client/plugins/index.cjs +3 -5
  52. package/dist/client/plugins/index.d.cts +5 -10
  53. package/dist/client/plugins/index.d.mts +5 -10
  54. package/dist/client/plugins/index.mjs +2 -4
  55. package/dist/client/react/index.cjs +6 -14
  56. package/dist/client/react/index.d.cts +402 -71
  57. package/dist/client/react/index.d.mts +402 -71
  58. package/dist/client/react/index.mjs +5 -13
  59. package/dist/client/solid/index.cjs +6 -14
  60. package/dist/client/solid/index.d.cts +393 -57
  61. package/dist/client/solid/index.d.mts +393 -57
  62. package/dist/client/solid/index.mjs +5 -13
  63. package/dist/client/svelte/index.cjs +5 -10
  64. package/dist/client/svelte/index.d.cts +400 -67
  65. package/dist/client/svelte/index.d.mts +400 -67
  66. package/dist/client/svelte/index.mjs +4 -10
  67. package/dist/client/vue/index.cjs +6 -14
  68. package/dist/client/vue/index.d.cts +401 -68
  69. package/dist/client/vue/index.d.mts +401 -68
  70. package/dist/client/vue/index.mjs +5 -13
  71. package/dist/{cookies-BTs1o992.mjs → cookies-D9aY_gJh.mjs} +25 -21
  72. package/dist/{cookies-BTl72THv.cjs → cookies-DQ52rcOy.cjs} +119 -115
  73. package/dist/crypto/index.cjs +10 -8
  74. package/dist/crypto/index.d.cts +5 -13
  75. package/dist/crypto/index.d.mts +5 -13
  76. package/dist/crypto/index.mjs +2 -5
  77. package/dist/{crypto-DH2Aa7jN.mjs → crypto-BH-hD0lJ.mjs} +7 -10
  78. package/dist/{crypto-DpSCnrTp.cjs → crypto-BITfWVwD.cjs} +24 -27
  79. package/dist/db/index.cjs +1135 -29
  80. package/dist/db/index.d.cts +1 -2
  81. package/dist/db/index.d.mts +1 -2
  82. package/dist/db/index.mjs +1115 -16
  83. package/dist/defu-D2h4S3X-.mjs +87 -0
  84. package/dist/defu-DWS5RPWt.cjs +134 -0
  85. package/dist/{email-verification-DI_0H4JC.cjs → email-verification-DOPnSgbI.cjs} +65 -71
  86. package/dist/{email-verification-C_lBu_JY.mjs → email-verification-YSR5n5lb.mjs} +23 -29
  87. package/dist/{hono-CO-zsqI-.mjs → hono-BAV2wQkK.mjs} +16 -33
  88. package/dist/hono-SVQuc5Ru.mjs +4 -0
  89. package/dist/hono-pgK4H_U1.cjs +9 -0
  90. package/dist/{hono-DnW5crl1.cjs → hono-tyFFJFdS.cjs} +42 -60
  91. package/dist/index-B86Cy0dE.d.cts +2 -0
  92. package/dist/index-B86Cy0dE.d.mts +2 -0
  93. package/dist/index.cjs +115 -150
  94. package/dist/index.d.cts +4 -5
  95. package/dist/index.d.mts +4 -5
  96. package/dist/index.mjs +46 -81
  97. package/dist/integrations/next-js.cjs +5 -9
  98. package/dist/integrations/next-js.d.cts +6 -14
  99. package/dist/integrations/next-js.d.mts +6 -14
  100. package/dist/integrations/next-js.mjs +4 -9
  101. package/dist/integrations/node.cjs +16 -14
  102. package/dist/integrations/node.d.cts +6 -14
  103. package/dist/integrations/node.d.mts +6 -14
  104. package/dist/integrations/node.mjs +15 -13
  105. package/dist/integrations/react-start.cjs +7 -11
  106. package/dist/integrations/react-start.d.cts +5 -13
  107. package/dist/integrations/react-start.d.mts +5 -13
  108. package/dist/integrations/react-start.mjs +6 -11
  109. package/dist/integrations/solid-start.cjs +3 -5
  110. package/dist/integrations/solid-start.d.cts +2 -5
  111. package/dist/integrations/solid-start.d.mts +2 -5
  112. package/dist/integrations/solid-start.mjs +2 -4
  113. package/dist/integrations/svelte-kit.cjs +6 -10
  114. package/dist/integrations/svelte-kit.d.cts +11 -23
  115. package/dist/integrations/svelte-kit.d.mts +11 -23
  116. package/dist/integrations/svelte-kit.mjs +5 -10
  117. package/dist/{ip-BjNYspCH.mjs → ip-6Lv2o42m.mjs} +4 -9
  118. package/dist/{ip-C17Qdq-G.cjs → ip-DPydExzV.cjs} +21 -27
  119. package/dist/{json--tl7Grvs.cjs → json-D3aq-nH2.cjs} +9 -13
  120. package/dist/{json-B1v2qRTQ.mjs → json-DooGMtnJ.mjs} +2 -5
  121. package/dist/{logged-CyGfp8_H.mjs → logged-B83SzMnJ.mjs} +6 -10
  122. package/dist/{logged-Dv3st5qc.cjs → logged-BIpCpnVY.cjs} +13 -18
  123. package/dist/{middleware-CE6OhDkq.mjs → middleware-Cakg4e1D.mjs} +2 -4
  124. package/dist/{middleware-CWvRH4EW.cjs → middleware-Cd-VkNxB.cjs} +17 -20
  125. package/dist/{node-sqlite-dialect-w4DAg0PH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
  126. package/dist/{test-utils/node-sqlite-dialect-BgJqjBOu.cjs → node-sqlite-dialect-D3QPFROH.cjs} +5 -9
  127. package/dist/oauth2/index.cjs +166 -22
  128. package/dist/oauth2/index.d.cts +5 -17
  129. package/dist/oauth2/index.d.mts +5 -17
  130. package/dist/oauth2/index.mjs +156 -16
  131. package/dist/{origin-check-DjLTuZQ8.cjs → origin-check-BflGhEEN.cjs} +34 -38
  132. package/dist/{origin-check-8Gajklvh.mjs → origin-check-CRgs1M7k.mjs} +13 -16
  133. package/dist/{parser-B25ylT5u.mjs → parser-CqwvpF6l.cjs} +12 -10
  134. package/dist/{parser-B_wxvaAr.cjs → parser-DcKDjjHO.mjs} +7 -22
  135. package/dist/plugins/access/index.cjs +38 -4
  136. package/dist/plugins/access/index.d.cts +36 -2
  137. package/dist/plugins/access/index.d.mts +36 -2
  138. package/dist/plugins/access/index.mjs +36 -3
  139. package/dist/plugins/bearer/index.cjs +52 -7
  140. package/dist/plugins/bearer/index.d.cts +27 -4
  141. package/dist/plugins/bearer/index.d.mts +27 -4
  142. package/dist/plugins/bearer/index.mjs +51 -7
  143. package/dist/plugins/index.cjs +1385 -842
  144. package/dist/plugins/index.d.cts +489 -7566
  145. package/dist/plugins/index.d.mts +489 -7566
  146. package/dist/plugins/index.mjs +1118 -576
  147. package/dist/plugins/passkey/index.cjs +551 -15
  148. package/dist/plugins/passkey/index.d.cts +123 -4
  149. package/dist/plugins/passkey/index.d.mts +123 -4
  150. package/dist/plugins/passkey/index.mjs +547 -15
  151. package/dist/{chunk-BFnQceUY.mjs → rolldown-runtime-BKpuH2hG.mjs} +6 -7
  152. package/dist/{chunk-fPmz2rbM.cjs → rolldown-runtime-C_Pgydhf.cjs} +22 -24
  153. package/dist/{schema-DTIwLLmf.mjs → schema-CFCpv0tK.mjs} +3 -6
  154. package/dist/{schema-CirKflVs.cjs → schema-b-lKhMkG.cjs} +51 -55
  155. package/dist/{session-CM3rmOYF.mjs → session-BGjJgihS.mjs} +51 -74
  156. package/dist/{session-Cwrj4GfV.cjs → session-CzZSMmQC.cjs} +197 -219
  157. package/dist/shared.d.cts +1581 -0
  158. package/dist/shared.d.mts +1581 -0
  159. package/dist/social-providers/index.cjs +9 -9
  160. package/dist/social-providers/index.d.cts +1 -1
  161. package/dist/social-providers/index.d.mts +1 -1
  162. package/dist/social-providers/index.mjs +3 -5
  163. package/dist/social-providers-CjPww-qf.mjs +6 -0
  164. package/dist/social-providers-D7w_7Ym8.cjs +10 -0
  165. package/dist/{state-CvSihlVT.cjs → state-2OrNjOO-.cjs} +24 -24
  166. package/dist/{state-CQghgH9I.mjs → state-Dooeisfq.mjs} +17 -17
  167. package/dist/{bun-sqlite-dialect-DPgTzc0w.cjs → test-utils/bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
  168. package/dist/{bun-sqlite-dialect-6NqeV3px.mjs → test-utils/bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
  169. package/dist/test-utils/index.cjs +8831 -7941
  170. package/dist/test-utils/index.d.cts +310 -12440
  171. package/dist/test-utils/index.d.mts +313 -12440
  172. package/dist/test-utils/index.mjs +8591 -7701
  173. package/dist/test-utils/{node-sqlite-dialect-DAQXiobH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
  174. package/dist/{node-sqlite-dialect-DP11CB0y.cjs → test-utils/node-sqlite-dialect-D3QPFROH.cjs} +5 -9
  175. package/dist/types/index.d.cts +2 -3
  176. package/dist/types/index.d.mts +2 -3
  177. package/dist/types/index.mjs +1 -1
  178. package/dist/{url-BoUuoIwZ.mjs → url-CJtdrrUu.mjs} +12 -13
  179. package/dist/{url-Ce7CVaQD.cjs → url-DjCmCUHS.cjs} +42 -44
  180. package/dist/utils/cookies.cjs +29 -30
  181. package/dist/utils/cookies.d.cts +21 -25
  182. package/dist/utils/cookies.d.mts +20 -24
  183. package/dist/utils/cookies.mjs +2 -7
  184. package/dist/utils-C7OHyfHa.mjs +4 -0
  185. package/dist/utils-iX0Vy_UL.cjs +3 -0
  186. package/package.json +40 -30
  187. package/dist/access-BZ7-AbTM.cjs +0 -51
  188. package/dist/access-D0DRqUKC.mjs +0 -39
  189. package/dist/bearer-DDzrp5M7.cjs +0 -60
  190. package/dist/bearer-WZcs7gxL.mjs +0 -54
  191. package/dist/db-4tUsQJXd.mjs +0 -1119
  192. package/dist/db-ChMbb_U-.cjs +0 -1180
  193. package/dist/defu-BmOYq4PU.cjs +0 -34
  194. package/dist/defu-D9ZTXqlo.mjs +0 -28
  195. package/dist/hono-C14rpOEa.cjs +0 -13
  196. package/dist/hono-CoKYWnXA.mjs +0 -7
  197. package/dist/hono-D0VqxVy1.d.mts +0 -18
  198. package/dist/hono-DOM31WQz.d.cts +0 -18
  199. package/dist/index-BCTFWP_o.d.mts +0 -992
  200. package/dist/index-BDhhaE6Y.d.cts +0 -3
  201. package/dist/index-BVRfQy6L.d.mts +0 -992
  202. package/dist/index-Baarsq5J.d.mts +0 -33
  203. package/dist/index-By364WbF.d.cts +0 -992
  204. package/dist/index-BzWwMgxr.d.cts +0 -992
  205. package/dist/index-CF9iq55a.d.mts +0 -3
  206. package/dist/index-CJD2yB-W.d.cts +0 -33
  207. package/dist/index-CRt_fppq.d.mts +0 -41
  208. package/dist/index-CdLyn7qP.d.cts +0 -41
  209. package/dist/index-CsWF3f7U.d.cts +0 -13350
  210. package/dist/index-CzidsAyA.d.mts +0 -13350
  211. package/dist/index-DvW-GCcI.d.cts +0 -33
  212. package/dist/index-f-5OJ9yV.d.cts +0 -13350
  213. package/dist/index-rFv8Hxld.d.mts +0 -13350
  214. package/dist/index-ztVZPQdV.d.mts +0 -33
  215. package/dist/kysely-adapter-CtIdoHa8.mjs +0 -270
  216. package/dist/kysely-adapter-QZTx077T.cjs +0 -288
  217. package/dist/memory-adapter-17RZd5df.cjs +0 -154
  218. package/dist/memory-adapter-Dp4XdCZK.mjs +0 -148
  219. package/dist/oauth2-5RL4cVNS.cjs +0 -177
  220. package/dist/oauth2-C56wz-n9.mjs +0 -159
  221. package/dist/passkey-BTT-v5c-.cjs +0 -512
  222. package/dist/passkey-CzY_W2us.mjs +0 -505
  223. package/dist/request-1NL_1lyJ.mjs +0 -58
  224. package/dist/request-CPNlp-DK.cjs +0 -100
  225. package/dist/social-providers-B8RK5yqI.mjs +0 -9
  226. package/dist/social-providers-BmFOIIPk.cjs +0 -13
  227. package/dist/utils-44aDDP8f.cjs +0 -2
  228. package/dist/utils-D4vZd1-9.mjs +0 -4
@@ -1,15 +1,551 @@
1
- require('../../hono-C14rpOEa.cjs');
2
- require('../../crypto-DpSCnrTp.cjs');
3
- require('../../json--tl7Grvs.cjs');
4
- require('../../cookies-BTl72THv.cjs');
5
- require('../../logged-Dv3st5qc.cjs');
6
- require('../../url-Ce7CVaQD.cjs');
7
- require('../../middleware-CWvRH4EW.cjs');
8
- require('../../session-Cwrj4GfV.cjs');
9
- require('../../state-CvSihlVT.cjs');
10
- require('../../request-CPNlp-DK.cjs');
11
- require('../../utils-44aDDP8f.cjs');
12
- require('../../schema-CirKflVs.cjs');
13
- const require_passkey = require('../../passkey-BTT-v5c-.cjs');
14
-
15
- exports.passkey = require_passkey.passkey;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_rolldown_runtime = require("../../rolldown-runtime-C_Pgydhf.cjs");
3
+ const require_session = require("../../session-CzZSMmQC.cjs");
4
+ const require_schema = require("../../schema-b-lKhMkG.cjs");
5
+ require("../../utils-iX0Vy_UL.cjs");
6
+ const require_cookies = require("../../cookies-DQ52rcOy.cjs");
7
+ let _faire_auth_core_env = require("@faire-auth/core/env");
8
+ let _faire_auth_core_factory = require("@faire-auth/core/factory");
9
+ let _faire_auth_core_static = require("@faire-auth/core/static");
10
+ let _faire_auth_core_utils = require("@faire-auth/core/utils");
11
+ let _faire_auth_core_datatypes = require("@faire-auth/core/datatypes");
12
+ let zod = require("zod");
13
+ zod = require_rolldown_runtime.__toESM(zod, 1);
14
+ let _simplewebauthn_server = require("@simplewebauthn/server");
15
+ let _faire_auth_core_crypto = require("@faire-auth/core/crypto");
16
+ // src/plugins/passkey/index.ts
17
+ const getRpID = (options, baseURL) => options.rpID || (baseURL ? new URL(baseURL).hostname : "localhost");
18
+ const passkeySchema = zod.object({
19
+ id: zod.string(),
20
+ name: zod.string().optional(),
21
+ publicKey: zod.string(),
22
+ userId: zod.string(),
23
+ credentialID: zod.string(),
24
+ counter: zod.number().int().nonnegative(),
25
+ deviceType: zod.enum(["singleDevice", "multiDevice"]),
26
+ backedUp: zod.boolean(),
27
+ transports: zod.string().optional(),
28
+ createdAt: zod.date().or(zod.iso.datetime()),
29
+ aaguid: zod.string().optional()
30
+ });
31
+ const passkey = (options) => {
32
+ const opts = {
33
+ origin: null,
34
+ ...options,
35
+ advanced: {
36
+ webAuthnChallengeCookie: "better-auth-passkey",
37
+ ...options?.advanced
38
+ }
39
+ };
40
+ const expirationTime = new Date(Date.now() + 3e5);
41
+ const currentTime = /* @__PURE__ */ new Date();
42
+ const maxAgeInSeconds = Math.floor((expirationTime.getTime() - currentTime.getTime()) / 1e3);
43
+ const ERROR_CODES = {
44
+ CHALLENGE_NOT_FOUND: "Challenge not found",
45
+ YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: "You are not allowed to register this passkey",
46
+ FAILED_TO_VERIFY_REGISTRATION: "Failed to verify registration",
47
+ PASSKEY_NOT_FOUND: "Passkey not found",
48
+ AUTHENTICATION_FAILED: "Authentication failed",
49
+ UNABLE_TO_CREATE_SESSION: "Unable to create session",
50
+ FAILED_TO_UPDATE_PASSKEY: "Failed to update passkey"
51
+ };
52
+ return {
53
+ id: "passkey",
54
+ routes: {
55
+ generatePasskeyRegistrationOptions: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
56
+ operationId: "generatePasskeyRegistrationOptions",
57
+ method: "get",
58
+ path: "/passkey/generate-register-options",
59
+ client: false,
60
+ description: "Generate registration options for a new passkey",
61
+ middleware: [require_session.freshSessionMiddleware],
62
+ request: (0, _faire_auth_core_factory.req)().qry(zod.object({
63
+ authenticatorAttachment: zod.enum(["platform", "cross-platform"]).optional().openapi({ description: `Type of authenticator to use for registration.
64
+ "platform" for device-specific authenticators,
65
+ "cross-platform" for authenticators that can be used across devices.` }),
66
+ name: zod.string().optional().openapi({ description: `Optional custom name for the passkey.
67
+ This can help identify the passkey when managing multiple credentials.` })
68
+ })).bld(),
69
+ responses: (0, _faire_auth_core_factory.res)(zod.object({
70
+ challenge: zod.base64url(),
71
+ timeout: zod.number().optional(),
72
+ rp: zod.object({
73
+ name: zod.string(),
74
+ id: zod.string().optional()
75
+ }),
76
+ user: zod.object({
77
+ id: zod.string(),
78
+ name: zod.string(),
79
+ displayName: zod.string()
80
+ }),
81
+ pubKeyCredParams: zod.array(zod.object({
82
+ type: zod.string(),
83
+ alg: zod.number()
84
+ })),
85
+ excludeCredentials: zod.array(zod.object({
86
+ id: zod.string(),
87
+ type: zod.string(),
88
+ transports: zod.array(zod.enum([
89
+ "ble",
90
+ "cable",
91
+ "hybrid",
92
+ "internal",
93
+ "nfc",
94
+ "smart-card",
95
+ "usb"
96
+ ])).optional()
97
+ })).optional(),
98
+ authenticatorSelection: zod.object({
99
+ authenticatorAttachment: zod.string(),
100
+ requireResidentKey: zod.boolean(),
101
+ userVerification: zod.string()
102
+ }).partial().optional(),
103
+ attestation: zod.string(),
104
+ extensions: zod.record(zod.string(), zod.any())
105
+ }).transform(_faire_auth_core_utils.toSuccess)).err(401).bld()
106
+ }), (authOptions) => async (ctx) => {
107
+ const session = ctx.get("session");
108
+ const { name, authenticatorAttachment } = ctx.req.valid("query");
109
+ const userPasskeys = await ctx.get("context").adapter.findMany({
110
+ model: "passkey",
111
+ where: [{
112
+ field: "userId",
113
+ value: session.user.id
114
+ }]
115
+ });
116
+ const userID = new TextEncoder().encode((0, _faire_auth_core_crypto.generateRandomString)(32, "a-z", "0-9"));
117
+ let options;
118
+ options = await (0, _simplewebauthn_server.generateRegistrationOptions)({
119
+ rpName: opts.rpName || ctx.get("context").appName,
120
+ rpID: getRpID(opts, authOptions.baseURL),
121
+ userID,
122
+ userName: name ?? session.user.email ?? session.user.id,
123
+ userDisplayName: session.user.email ?? session.user.id,
124
+ attestationType: "none",
125
+ excludeCredentials: userPasskeys.map((passkey) => ({
126
+ id: passkey.credentialID,
127
+ transports: passkey.transports?.split(",")
128
+ })),
129
+ authenticatorSelection: {
130
+ residentKey: "preferred",
131
+ userVerification: "preferred",
132
+ ...opts.authenticatorSelection ?? {},
133
+ ...authenticatorAttachment && { authenticatorAttachment }
134
+ }
135
+ });
136
+ const id = (0, _faire_auth_core_crypto.generateId)(32);
137
+ const webAuthnCookie = ctx.get("context").createAuthCookie(opts.advanced.webAuthnChallengeCookie);
138
+ await (0, require_cookies.cookies_exports.setSignedCookie)(ctx, webAuthnCookie.name, id, ctx.get("context").secret, {
139
+ ...webAuthnCookie.attributes,
140
+ maxAge: maxAgeInSeconds
141
+ });
142
+ await ctx.get("context").internalAdapter.createVerificationValue({
143
+ identifier: id,
144
+ value: JSON.stringify({
145
+ expectedChallenge: options.challenge,
146
+ userData: { id: session.user.id }
147
+ }),
148
+ expiresAt: expirationTime
149
+ });
150
+ return ctx.render(options, 200);
151
+ }),
152
+ generatePasskeyAuthenticationOptions: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
153
+ operationId: "generatePasskeyAuthenticationOptions",
154
+ method: "post",
155
+ path: "/passkey/generate-authenticate-options",
156
+ description: "Generate authentication options for a passkey",
157
+ request: (0, _faire_auth_core_factory.req)().bdy(zod.object({ email: _faire_auth_core_factory.emailSchema.openapi({ description: "The email address of the user" }).optional() })).bld(),
158
+ responses: (0, _faire_auth_core_factory.res)(zod.object({
159
+ challenge: zod.base64url(),
160
+ timeout: zod.number().optional(),
161
+ rpId: zod.string().optional(),
162
+ allowCredentials: zod.array(zod.object({
163
+ id: zod.string(),
164
+ type: zod.string(),
165
+ transports: zod.array(zod.enum([
166
+ "ble",
167
+ "cable",
168
+ "hybrid",
169
+ "internal",
170
+ "nfc",
171
+ "smart-card",
172
+ "usb"
173
+ ])).optional()
174
+ })).optional(),
175
+ userVerification: zod.enum([
176
+ "discouraged",
177
+ "preferred",
178
+ "required"
179
+ ]).optional(),
180
+ extensions: zod.record(zod.string(), zod.any()).optional()
181
+ }).transform(_faire_auth_core_utils.toSuccess)).bld()
182
+ }), (authOptions) => async (ctx) => {
183
+ const session = await require_session.getSessionFromCtx(ctx);
184
+ let userPasskeys = [];
185
+ if (!(session instanceof Response)) userPasskeys = await ctx.get("context").adapter.findMany({
186
+ model: "passkey",
187
+ where: [{
188
+ field: "userId",
189
+ value: session.user.id
190
+ }]
191
+ });
192
+ const options = await (0, _simplewebauthn_server.generateAuthenticationOptions)({
193
+ rpID: getRpID(opts, authOptions.baseURL),
194
+ userVerification: "preferred",
195
+ ...userPasskeys.length > 0 && { allowCredentials: userPasskeys.map((passkey) => ({
196
+ id: passkey.credentialID,
197
+ transports: passkey.transports?.split(",")
198
+ })) }
199
+ });
200
+ const data = {
201
+ expectedChallenge: options.challenge,
202
+ userData: { id: "user" in session ? session.user.id : "" }
203
+ };
204
+ const id = (0, _faire_auth_core_crypto.generateId)(32);
205
+ const webAuthnCookie = ctx.get("context").createAuthCookie(opts.advanced.webAuthnChallengeCookie);
206
+ await (0, require_cookies.cookies_exports.setSignedCookie)(ctx, webAuthnCookie.name, id, ctx.get("context").secret, {
207
+ ...webAuthnCookie.attributes,
208
+ maxAge: maxAgeInSeconds
209
+ });
210
+ await ctx.get("context").internalAdapter.createVerificationValue({
211
+ identifier: id,
212
+ value: JSON.stringify(data),
213
+ expiresAt: expirationTime
214
+ });
215
+ return ctx.render(options, 200);
216
+ }),
217
+ verifyPasskeyRegistration: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
218
+ operationId: "verifyPasskeyRegistration",
219
+ method: "post",
220
+ path: "/passkey/verify-registration",
221
+ description: "Verify registration of a new passkey",
222
+ middleware: [require_session.freshSessionMiddleware],
223
+ request: (0, _faire_auth_core_factory.req)().bdy(zod.object({
224
+ response: zod.any(),
225
+ name: zod.string().openapi({ description: "Name of the passkey" }).optional()
226
+ })).bld(),
227
+ responses: (0, _faire_auth_core_factory.res)(passkeySchema.transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(500, "Failed to verify registration").bld()
228
+ }), (authOptions) => async (ctx) => {
229
+ const origin = options?.origin ?? ctx.req.header("origin") ?? "";
230
+ if (!origin) return ctx.render({ success: _faire_auth_core_static.False }, 400);
231
+ const session = ctx.get("session");
232
+ const { response } = ctx.req.valid("json");
233
+ const webAuthnCookie = ctx.get("context").createAuthCookie(opts.advanced.webAuthnChallengeCookie);
234
+ const challengeId = await (0, require_cookies.cookies_exports.getSignedCookie)(ctx, ctx.get("context").secret, webAuthnCookie.name);
235
+ if (!challengeId) return ctx.render({
236
+ success: _faire_auth_core_static.False,
237
+ message: ERROR_CODES.CHALLENGE_NOT_FOUND
238
+ }, 400);
239
+ const data = await ctx.get("context").internalAdapter.findVerificationValue(challengeId);
240
+ if (!data) return ctx.render({
241
+ success: _faire_auth_core_static.False,
242
+ message: ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION
243
+ }, 400);
244
+ const { expectedChallenge, userData } = JSON.parse(data.value);
245
+ if (userData.id !== session.user.id) return ctx.render({
246
+ success: _faire_auth_core_static.False,
247
+ message: ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY
248
+ }, 401);
249
+ try {
250
+ const { verified, registrationInfo } = await (0, _simplewebauthn_server.verifyRegistrationResponse)({
251
+ response,
252
+ expectedChallenge,
253
+ expectedOrigin: origin,
254
+ expectedRPID: getRpID(opts, authOptions.baseURL),
255
+ requireUserVerification: false
256
+ });
257
+ if (!verified || !registrationInfo) return ctx.render({
258
+ success: _faire_auth_core_static.False,
259
+ message: ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION
260
+ }, 400);
261
+ const { aaguid, credentialDeviceType, credentialBackedUp, credential } = registrationInfo;
262
+ const pubKey = _faire_auth_core_datatypes.base64.encode(credential.publicKey);
263
+ const newPasskey = {
264
+ name: ctx.body.name,
265
+ userId: userData.id,
266
+ credentialID: credential.id,
267
+ publicKey: pubKey,
268
+ counter: credential.counter,
269
+ deviceType: credentialDeviceType,
270
+ transports: response.response.transports.join(","),
271
+ backedUp: credentialBackedUp,
272
+ createdAt: /* @__PURE__ */ new Date(),
273
+ aaguid
274
+ };
275
+ const newPasskeyRes = await ctx.get("context").adapter.create({
276
+ model: "passkey",
277
+ data: newPasskey
278
+ });
279
+ return ctx.render(newPasskeyRes, 200);
280
+ } catch (e) {
281
+ _faire_auth_core_env.logger.error(String(e));
282
+ return ctx.render({
283
+ success: _faire_auth_core_static.False,
284
+ message: ERROR_CODES.FAILED_TO_VERIFY_REGISTRATION
285
+ }, 500);
286
+ }
287
+ }),
288
+ verifyPasskeyAuthentication: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
289
+ operationId: "verifyPasskeyAuthentication",
290
+ method: "post",
291
+ path: "/passkey/verify-authentication",
292
+ description: "Verify authentication of a passkey",
293
+ $Infer: { body: {} },
294
+ request: (0, _faire_auth_core_factory.req)().bdy(zod.object({ response: zod.record(zod.string(), zod.any()) })).bld(),
295
+ responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SESSION_RESPONSE].default).err(400, "Origin missing, challenge not found, or auth failed").err(401, "Passkey not found or auth failed").err(500, "User not found or unable to create session").bld()
296
+ }), (authOptions) => async (ctx) => {
297
+ const origin = options?.origin ?? ctx.req.header("origin") ?? "";
298
+ if (!origin) return ctx.render({
299
+ success: _faire_auth_core_static.False,
300
+ message: "Origin missing"
301
+ }, 400);
302
+ const { response } = ctx.req.valid("json");
303
+ const webAuthnCookie = ctx.get("context").createAuthCookie(opts.advanced.webAuthnChallengeCookie);
304
+ const challengeId = await (0, require_cookies.cookies_exports.getSignedCookie)(ctx, ctx.get("context").secret, webAuthnCookie.name);
305
+ if (!challengeId) return ctx.render({
306
+ success: _faire_auth_core_static.False,
307
+ message: ERROR_CODES.CHALLENGE_NOT_FOUND
308
+ }, 400);
309
+ const data = await ctx.get("context").internalAdapter.findVerificationValue(challengeId);
310
+ if (!data) return ctx.render({
311
+ success: _faire_auth_core_static.False,
312
+ message: ERROR_CODES.CHALLENGE_NOT_FOUND
313
+ }, 400);
314
+ const { expectedChallenge } = JSON.parse(data.value);
315
+ const passkey = await ctx.get("context").adapter.findOne({
316
+ model: "passkey",
317
+ where: [{
318
+ field: "credentialID",
319
+ value: response["id"]
320
+ }]
321
+ });
322
+ if (!passkey) return ctx.render({
323
+ success: _faire_auth_core_static.False,
324
+ message: ERROR_CODES.PASSKEY_NOT_FOUND
325
+ }, 401);
326
+ try {
327
+ const verification = await (0, _simplewebauthn_server.verifyAuthenticationResponse)({
328
+ response,
329
+ expectedChallenge,
330
+ expectedOrigin: origin,
331
+ expectedRPID: getRpID(opts, authOptions.baseURL),
332
+ credential: {
333
+ id: passkey.credentialID,
334
+ publicKey: _faire_auth_core_datatypes.base64.decode(passkey.publicKey),
335
+ counter: passkey.counter,
336
+ transports: passkey.transports?.split(",")
337
+ },
338
+ requireUserVerification: false
339
+ });
340
+ const { verified } = verification;
341
+ if (!verified) return ctx.render({
342
+ success: _faire_auth_core_static.False,
343
+ message: ERROR_CODES.AUTHENTICATION_FAILED
344
+ }, 401);
345
+ await ctx.get("context").adapter.update({
346
+ model: "passkey",
347
+ where: [{
348
+ field: "id",
349
+ value: passkey.id
350
+ }],
351
+ update: { counter: verification.authenticationInfo.newCounter }
352
+ });
353
+ const s = await ctx.get("context").internalAdapter.createSession(passkey.userId);
354
+ if (!s) return ctx.render({
355
+ success: _faire_auth_core_static.False,
356
+ message: ERROR_CODES.UNABLE_TO_CREATE_SESSION
357
+ }, 500);
358
+ const user = await ctx.get("context").internalAdapter.findUserById(passkey.userId);
359
+ if (!user) return ctx.render({
360
+ success: _faire_auth_core_static.False,
361
+ message: "User not found"
362
+ }, 500);
363
+ await require_cookies.setSessionCookie(ctx, authOptions, {
364
+ session: s,
365
+ user
366
+ });
367
+ return ctx.render(s, 200);
368
+ } catch (e) {
369
+ ctx.get("context").logger.error("Failed to verify authentication", e);
370
+ return ctx.render({
371
+ success: _faire_auth_core_static.False,
372
+ message: ERROR_CODES.AUTHENTICATION_FAILED
373
+ }, 400);
374
+ }
375
+ }),
376
+ /**
377
+ * ### Endpoint
378
+ *
379
+ * GET `/passkey/list-user-passkeys`
380
+ *
381
+ * ### API Methods
382
+ *
383
+ * **server:**
384
+ * `auth.api.listPasskeys`
385
+ *
386
+ * **client:**
387
+ * `authClient.passkey.listUserPasskeys`
388
+ *
389
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-list-user-passkeys)
390
+ */
391
+ listPasskeys: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
392
+ operationId: "listPasskeys",
393
+ method: "get",
394
+ path: "/passkey/list-user-passkeys",
395
+ description: "List all passkeys for the authenticated user",
396
+ middleware: [require_session.sessionMiddleware()],
397
+ responses: (0, _faire_auth_core_factory.res)(zod.array(passkeySchema).openapi({ description: "Array of passkey objects associated with the user" }).transform(_faire_auth_core_utils.toSuccess)).err(401).bld()
398
+ }), (_authOptions) => async (ctx) => {
399
+ const session = ctx.get("session");
400
+ const passkeys = await ctx.get("context").adapter.findMany({
401
+ model: "passkey",
402
+ where: [{
403
+ field: "userId",
404
+ value: session.user.id
405
+ }]
406
+ });
407
+ return ctx.render(passkeys, 200);
408
+ }),
409
+ /**
410
+ * ### Endpoint
411
+ *
412
+ * POST `/passkey/delete-passkey`
413
+ *
414
+ * ### API Methods
415
+ *
416
+ * **server:**
417
+ * `auth.api.deletePasskey`
418
+ *
419
+ * **client:**
420
+ * `authClient.passkey.deletePasskey`
421
+ *
422
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-delete-passkey)
423
+ */
424
+ deletePasskey: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
425
+ operationId: "deletePasskey",
426
+ method: "post",
427
+ path: "/passkey/delete-passkey",
428
+ description: "Delete a specific passkey",
429
+ middleware: [require_session.sessionMiddleware()],
430
+ request: (0, _faire_auth_core_factory.req)().bdy(zod.object({ id: zod.string().openapi({ description: "The ID of the passkey to delete. Eg: \"some-passkey-id\"" }) })).bld(),
431
+ responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default, "Passkey deleted successfully").err(401).bld()
432
+ }), (_authOptions) => async (ctx) => {
433
+ await ctx.get("context").adapter.delete({
434
+ model: "passkey",
435
+ where: [{
436
+ field: "id",
437
+ value: ctx.req.valid("json").id
438
+ }]
439
+ });
440
+ return ctx.render({ success: _faire_auth_core_static.True }, 200);
441
+ }),
442
+ /**
443
+ * ### Endpoint
444
+ *
445
+ * POST `/passkey/update-passkey`
446
+ *
447
+ * ### API Methods
448
+ *
449
+ * **server:**
450
+ * `auth.api.updatePasskey`
451
+ *
452
+ * **client:**
453
+ * `authClient.passkey.updatePasskey`
454
+ *
455
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-update-passkey)
456
+ */
457
+ updatePasskey: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
458
+ operationId: "updatePasskey",
459
+ method: "post",
460
+ path: "/passkey/update-passkey",
461
+ description: "Update a specific passkey's name",
462
+ middleware: [require_session.sessionMiddleware()],
463
+ request: (0, _faire_auth_core_factory.req)().bdy(zod.object({
464
+ id: zod.string().openapi({ description: `The ID of the passkey which will be updated. Eg: \"passkey-id\"` }),
465
+ name: zod.string().openapi({ description: `The new name which the passkey will be updated to. Eg: \"my-new-passkey-name\"` })
466
+ })).bld(),
467
+ responses: (0, _faire_auth_core_factory.res)(passkeySchema.transform(_faire_auth_core_utils.toSuccess)).err(401, "Invalid session or not allowed to register").err(404, "Passkey not found").err(500, "Failed to update passkey").bld()
468
+ }), (_authOptions) => async (ctx) => {
469
+ const session = ctx.get("session");
470
+ const { id, name } = ctx.req.valid("json");
471
+ const passkey = await ctx.get("context").adapter.findOne({
472
+ model: "passkey",
473
+ where: [{
474
+ field: "id",
475
+ value: id
476
+ }]
477
+ });
478
+ if (!passkey) return ctx.render({
479
+ success: _faire_auth_core_static.False,
480
+ message: ERROR_CODES.PASSKEY_NOT_FOUND
481
+ }, 404);
482
+ if (passkey.userId !== session.user.id) return ctx.render({
483
+ success: _faire_auth_core_static.False,
484
+ message: ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY
485
+ }, 401);
486
+ const updatedPasskey = await ctx.get("context").adapter.update({
487
+ model: "passkey",
488
+ where: [{
489
+ field: "id",
490
+ value: id
491
+ }],
492
+ update: { name }
493
+ });
494
+ if (!updatedPasskey) return ctx.render({
495
+ success: _faire_auth_core_static.False,
496
+ message: ERROR_CODES.FAILED_TO_UPDATE_PASSKEY
497
+ }, 500);
498
+ return ctx.render(updatedPasskey, 200);
499
+ })
500
+ },
501
+ schema: require_schema.mergeSchema(schema, options?.schema),
502
+ $ERROR_CODES: ERROR_CODES
503
+ };
504
+ };
505
+ const schema = { passkey: { fields: {
506
+ name: {
507
+ type: "string",
508
+ required: false
509
+ },
510
+ publicKey: {
511
+ type: "string",
512
+ required: true
513
+ },
514
+ userId: {
515
+ type: "string",
516
+ references: {
517
+ model: "user",
518
+ field: "id"
519
+ },
520
+ required: true
521
+ },
522
+ credentialID: {
523
+ type: "string",
524
+ required: true
525
+ },
526
+ counter: {
527
+ type: "number",
528
+ required: true
529
+ },
530
+ deviceType: {
531
+ type: "string",
532
+ required: true
533
+ },
534
+ backedUp: {
535
+ type: "boolean",
536
+ required: true
537
+ },
538
+ transports: {
539
+ type: "string",
540
+ required: false
541
+ },
542
+ createdAt: {
543
+ type: "date",
544
+ required: false
545
+ },
546
+ aaguid: {
547
+ type: "string",
548
+ required: false
549
+ }
550
+ } } };
551
+ exports.passkey = passkey;
@@ -1,4 +1,123 @@
1
- import "../../index-CsWF3f7U.cjs";
2
- import "../../hono-DOM31WQz.cjs";
3
- import { n as PasskeyOptions, r as passkey, t as Passkey } from "../../index-By364WbF.cjs";
4
- export { Passkey, PasskeyOptions, passkey };
1
+ import { in as AuthEndpoint, xt as InferOptionSchema } from "../../shared.cjs";
2
+ import { CredentialDeviceType } from "@simplewebauthn/server";
3
+ export interface PasskeyOptions {
4
+ /**
5
+ * A unique identifier for your website. 'localhost' is okay for
6
+ * local dev
7
+ *
8
+ * @default "localhost"
9
+ */
10
+ rpID?: string;
11
+ /**
12
+ * Human-readable title for your website
13
+ *
14
+ * @default "Better Auth"
15
+ */
16
+ rpName?: string;
17
+ /**
18
+ * The URL at which registrations and authentications should occur.
19
+ * `http://localhost` and `http://localhost:PORT` are also valid.
20
+ * Do NOT include any trailing /
21
+ *
22
+ * if this isn't provided. The client itself will
23
+ * pass this value.
24
+ */
25
+ origin?: string | null;
26
+ /**
27
+ * Allow customization of the authenticatorSelection options
28
+ * during passkey registration.
29
+ */
30
+ authenticatorSelection?: AuthenticatorSelectionCriteria;
31
+ /**
32
+ * Advanced options
33
+ */
34
+ advanced?: {
35
+ webAuthnChallengeCookie?: string;
36
+ };
37
+ /**
38
+ * Schema for the passkey model
39
+ */
40
+ schema?: InferOptionSchema<typeof schema>;
41
+ }
42
+ export type Passkey = {
43
+ id: string;
44
+ name?: string;
45
+ publicKey: string;
46
+ userId: string;
47
+ credentialID: string;
48
+ counter: number;
49
+ deviceType: CredentialDeviceType;
50
+ backedUp: boolean;
51
+ transports?: string;
52
+ createdAt: Date;
53
+ aaguid?: string;
54
+ };
55
+ export declare const passkey: (options?: PasskeyOptions) => {
56
+ id: string;
57
+ routes: {
58
+ generatePasskeyRegistrationOptions: AuthEndpoint<any>;
59
+ generatePasskeyAuthenticationOptions: AuthEndpoint<any>;
60
+ verifyPasskeyRegistration: AuthEndpoint<any>;
61
+ verifyPasskeyAuthentication: AuthEndpoint<any>;
62
+ /**
63
+ * ### Endpoint
64
+ *
65
+ * GET `/passkey/list-user-passkeys`
66
+ *
67
+ * ### API Methods
68
+ *
69
+ * **server:**
70
+ * `auth.api.listPasskeys`
71
+ *
72
+ * **client:**
73
+ * `authClient.passkey.listUserPasskeys`
74
+ *
75
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-list-user-passkeys)
76
+ */
77
+ listPasskeys: AuthEndpoint<any>;
78
+ /**
79
+ * ### Endpoint
80
+ *
81
+ * POST `/passkey/delete-passkey`
82
+ *
83
+ * ### API Methods
84
+ *
85
+ * **server:**
86
+ * `auth.api.deletePasskey`
87
+ *
88
+ * **client:**
89
+ * `authClient.passkey.deletePasskey`
90
+ *
91
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-delete-passkey)
92
+ */
93
+ deletePasskey: AuthEndpoint<any>;
94
+ /**
95
+ * ### Endpoint
96
+ *
97
+ * POST `/passkey/update-passkey`
98
+ *
99
+ * ### API Methods
100
+ *
101
+ * **server:**
102
+ * `auth.api.updatePasskey`
103
+ *
104
+ * **client:**
105
+ * `authClient.passkey.updatePasskey`
106
+ *
107
+ * @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/passkey#api-method-passkey-update-passkey)
108
+ */
109
+ updatePasskey: AuthEndpoint<any>;
110
+ };
111
+ schema: FaireAuthPluginDBSchema;
112
+ $ERROR_CODES: {
113
+ CHALLENGE_NOT_FOUND: string;
114
+ YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: string;
115
+ FAILED_TO_VERIFY_REGISTRATION: string;
116
+ PASSKEY_NOT_FOUND: string;
117
+ AUTHENTICATION_FAILED: string;
118
+ UNABLE_TO_CREATE_SESSION: string;
119
+ FAILED_TO_UPDATE_PASSKEY: string;
120
+ };
121
+ };
122
+ declare const schema: FaireAuthPluginDBSchema;
123
+ export {};