@masheev/better-auth 0.0.0-stage → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +31 -2
  3. package/TYPE-PATCH-NOTICE.md +9 -0
  4. package/TYPE-PATCH-PROVENANCE.json +267 -0
  5. package/dist/_virtual/_rolldown/runtime.mjs +27 -0
  6. package/dist/adapters/drizzle-adapter/index.d.mts +1 -0
  7. package/dist/adapters/drizzle-adapter/index.mjs +2 -0
  8. package/dist/adapters/index.d.mts +26 -0
  9. package/dist/adapters/index.mjs +9 -0
  10. package/dist/adapters/kysely-adapter/index.d.mts +1 -0
  11. package/dist/adapters/kysely-adapter/index.mjs +2 -0
  12. package/dist/adapters/memory-adapter/index.d.mts +1 -0
  13. package/dist/adapters/memory-adapter/index.mjs +2 -0
  14. package/dist/adapters/mongodb-adapter/index.d.mts +1 -0
  15. package/dist/adapters/mongodb-adapter/index.mjs +2 -0
  16. package/dist/adapters/prisma-adapter/index.d.mts +1 -0
  17. package/dist/adapters/prisma-adapter/index.mjs +2 -0
  18. package/dist/api/dispatch.d.mts +34 -0
  19. package/dist/api/dispatch.mjs +275 -0
  20. package/dist/api/index.d.mts +4053 -0
  21. package/dist/api/index.mjs +220 -0
  22. package/dist/api/middlewares/authorization.d.mts +69 -0
  23. package/dist/api/middlewares/authorization.mjs +78 -0
  24. package/dist/api/middlewares/index.d.mts +2 -0
  25. package/dist/api/middlewares/origin-check.d.mts +17 -0
  26. package/dist/api/middlewares/origin-check.mjs +155 -0
  27. package/dist/api/rate-limiter/index.mjs +318 -0
  28. package/dist/api/routes/account.d.mts +413 -0
  29. package/dist/api/routes/account.mjs +619 -0
  30. package/dist/api/routes/callback.d.mts +32 -0
  31. package/dist/api/routes/callback.mjs +261 -0
  32. package/dist/api/routes/email-verification.d.mts +160 -0
  33. package/dist/api/routes/email-verification.mjs +324 -0
  34. package/dist/api/routes/error.d.mts +27 -0
  35. package/dist/api/routes/error.mjs +387 -0
  36. package/dist/api/routes/index.d.mts +12 -0
  37. package/dist/api/routes/ok.d.mts +35 -0
  38. package/dist/api/routes/ok.mjs +27 -0
  39. package/dist/api/routes/password.d.mts +182 -0
  40. package/dist/api/routes/password.mjs +206 -0
  41. package/dist/api/routes/session.d.mts +450 -0
  42. package/dist/api/routes/session.mjs +481 -0
  43. package/dist/api/routes/sign-in.d.mts +186 -0
  44. package/dist/api/routes/sign-in.mjs +368 -0
  45. package/dist/api/routes/sign-out.d.mts +51 -0
  46. package/dist/api/routes/sign-out.mjs +96 -0
  47. package/dist/api/routes/sign-up.d.mts +159 -0
  48. package/dist/api/routes/sign-up.mjs +275 -0
  49. package/dist/api/routes/update-session.d.mts +74 -0
  50. package/dist/api/routes/update-session.mjs +57 -0
  51. package/dist/api/routes/update-user.d.mts +428 -0
  52. package/dist/api/routes/update-user.mjs +522 -0
  53. package/dist/api/state/oauth.d.mts +53 -0
  54. package/dist/api/state/oauth.mjs +38 -0
  55. package/dist/api/state/should-session-refresh.d.mts +12 -0
  56. package/dist/api/state/should-session-refresh.mjs +13 -0
  57. package/dist/api/to-auth-endpoints.mjs +60 -0
  58. package/dist/auth/base.mjs +66 -0
  59. package/dist/auth/full.d.mts +28 -0
  60. package/dist/auth/full.mjs +29 -0
  61. package/dist/auth/minimal.d.mts +10 -0
  62. package/dist/auth/minimal.mjs +11 -0
  63. package/dist/auth/trusted-origins.mjs +106 -0
  64. package/dist/client/broadcast-channel.d.mts +19 -0
  65. package/dist/client/broadcast-channel.mjs +44 -0
  66. package/dist/client/config.d.mts +90 -0
  67. package/dist/client/config.mjs +113 -0
  68. package/dist/client/equality.d.mts +19 -0
  69. package/dist/client/equality.mjs +42 -0
  70. package/dist/client/fetch-plugins.mjs +17 -0
  71. package/dist/client/focus-manager.d.mts +10 -0
  72. package/dist/client/focus-manager.mjs +30 -0
  73. package/dist/client/index.d.mts +35 -0
  74. package/dist/client/index.mjs +22 -0
  75. package/dist/client/lynx/index.d.mts +43 -0
  76. package/dist/client/lynx/index.mjs +22 -0
  77. package/dist/client/lynx/lynx-store.d.mts +46 -0
  78. package/dist/client/lynx/lynx-store.mjs +44 -0
  79. package/dist/client/online-manager.d.mts +11 -0
  80. package/dist/client/online-manager.mjs +33 -0
  81. package/dist/client/parser.d.mts +10 -0
  82. package/dist/client/parser.mjs +70 -0
  83. package/dist/client/path-to-object.d.mts +113 -0
  84. package/dist/client/plugins/index.d.mts +44 -0
  85. package/dist/client/plugins/index.mjs +30 -0
  86. package/dist/client/plugins/infer-plugin.d.mts +16 -0
  87. package/dist/client/plugins/infer-plugin.mjs +11 -0
  88. package/dist/client/proxy.mjs +78 -0
  89. package/dist/client/query.d.mts +23 -0
  90. package/dist/client/query.mjs +124 -0
  91. package/dist/client/react/index.d.mts +44 -0
  92. package/dist/client/react/index.mjs +22 -0
  93. package/dist/client/react/react-store.d.mts +46 -0
  94. package/dist/client/react/react-store.mjs +44 -0
  95. package/dist/client/session-atom.d.mts +11 -0
  96. package/dist/client/session-atom.mjs +178 -0
  97. package/dist/client/session-refresh.d.mts +20 -0
  98. package/dist/client/session-refresh.mjs +131 -0
  99. package/dist/client/solid/index.d.mts +44 -0
  100. package/dist/client/solid/index.mjs +22 -0
  101. package/dist/client/solid/solid-store.mjs +21 -0
  102. package/dist/client/svelte/index.d.mts +44 -0
  103. package/dist/client/svelte/index.mjs +18 -0
  104. package/dist/client/types.d.mts +51 -0
  105. package/dist/client/vanilla.d.mts +42 -0
  106. package/dist/client/vanilla.mjs +18 -0
  107. package/dist/client/vue/index.d.mts +67 -0
  108. package/dist/client/vue/index.mjs +54 -0
  109. package/dist/client/vue/vue-store.mjs +23 -0
  110. package/dist/context/create-context.mjs +235 -0
  111. package/dist/context/helpers.mjs +158 -0
  112. package/dist/context/init-minimal.mjs +17 -0
  113. package/dist/context/init.mjs +19 -0
  114. package/dist/context/secret-utils.mjs +53 -0
  115. package/dist/context/store-capabilities.mjs +12 -0
  116. package/dist/cookies/cache.mjs +33 -0
  117. package/dist/cookies/cookie-utils.d.mts +72 -0
  118. package/dist/cookies/cookie-utils.mjs +203 -0
  119. package/dist/cookies/index.d.mts +124 -0
  120. package/dist/cookies/index.mjs +350 -0
  121. package/dist/cookies/jwt.mjs +44 -0
  122. package/dist/cookies/session-store.d.mts +32 -0
  123. package/dist/cookies/session-store.mjs +183 -0
  124. package/dist/crypto/buffer.d.mts +7 -0
  125. package/dist/crypto/buffer.mjs +16 -0
  126. package/dist/crypto/index.d.mts +32 -0
  127. package/dist/crypto/index.mjs +69 -0
  128. package/dist/crypto/jwt.d.mts +9 -0
  129. package/dist/crypto/jwt.mjs +141 -0
  130. package/dist/crypto/password.d.mts +13 -0
  131. package/dist/crypto/password.mjs +14 -0
  132. package/dist/crypto/random.d.mts +4 -0
  133. package/dist/crypto/random.mjs +5 -0
  134. package/dist/db/adapter-base.d.mts +7 -0
  135. package/dist/db/adapter-base.mjs +25 -0
  136. package/dist/db/adapter-kysely.d.mts +7 -0
  137. package/dist/db/adapter-kysely.mjs +17 -0
  138. package/dist/db/field-converter.d.mts +7 -0
  139. package/dist/db/field-converter.mjs +19 -0
  140. package/dist/db/field.d.mts +41 -0
  141. package/dist/db/get-migration.d.mts +56 -0
  142. package/dist/db/get-migration.mjs +685 -0
  143. package/dist/db/get-schema.d.mts +13 -0
  144. package/dist/db/get-schema.mjs +39 -0
  145. package/dist/db/index.d.mts +10 -0
  146. package/dist/db/index.mjs +35 -0
  147. package/dist/db/internal-adapter.d.mts +14 -0
  148. package/dist/db/internal-adapter.mjs +951 -0
  149. package/dist/db/revoke-unproven-account-access.d.mts +21 -0
  150. package/dist/db/revoke-unproven-account-access.mjs +58 -0
  151. package/dist/db/schema.d.mts +62 -0
  152. package/dist/db/schema.mjs +161 -0
  153. package/dist/db/to-zod.d.mts +35 -0
  154. package/dist/db/to-zod.mjs +23 -0
  155. package/dist/db/verification-token-storage.mjs +25 -0
  156. package/dist/db/with-hooks.d.mts +37 -0
  157. package/dist/db/with-hooks.mjs +255 -0
  158. package/dist/index.d.mts +30 -0
  159. package/dist/index.mjs +17 -0
  160. package/dist/integrations/cookie-plugin-guard.mjs +18 -0
  161. package/dist/integrations/next-js.d.mts +29 -0
  162. package/dist/integrations/next-js.mjs +105 -0
  163. package/dist/integrations/node.d.mts +11 -0
  164. package/dist/integrations/node.mjs +13 -0
  165. package/dist/integrations/solid-start.d.mts +22 -0
  166. package/dist/integrations/solid-start.mjs +15 -0
  167. package/dist/integrations/svelte-kit.d.mts +38 -0
  168. package/dist/integrations/svelte-kit.mjs +57 -0
  169. package/dist/integrations/tanstack-start-solid.d.mts +33 -0
  170. package/dist/integrations/tanstack-start-solid.mjs +57 -0
  171. package/dist/integrations/tanstack-start.d.mts +33 -0
  172. package/dist/integrations/tanstack-start.mjs +57 -0
  173. package/dist/oauth2/account-key.mjs +43 -0
  174. package/dist/oauth2/errors.mjs +49 -0
  175. package/dist/oauth2/index.d.mts +5 -0
  176. package/dist/oauth2/index.mjs +5 -0
  177. package/dist/oauth2/link-account.d.mts +96 -0
  178. package/dist/oauth2/link-account.mjs +329 -0
  179. package/dist/oauth2/state.d.mts +54 -0
  180. package/dist/oauth2/state.mjs +67 -0
  181. package/dist/oauth2/utils.d.mts +11 -0
  182. package/dist/oauth2/utils.mjs +33 -0
  183. package/dist/package.mjs +4 -0
  184. package/dist/plugins/access/access.d.mts +17 -0
  185. package/dist/plugins/access/access.mjs +78 -0
  186. package/dist/plugins/access/index.d.mts +3 -0
  187. package/dist/plugins/access/index.mjs +2 -0
  188. package/dist/plugins/access/types.d.mts +24 -0
  189. package/dist/plugins/additional-fields/client.d.mts +100 -0
  190. package/dist/plugins/additional-fields/client.mjs +11 -0
  191. package/dist/plugins/admin/access/index.d.mts +2 -0
  192. package/dist/plugins/admin/access/index.mjs +2 -0
  193. package/dist/plugins/admin/access/statement.d.mts +51 -0
  194. package/dist/plugins/admin/access/statement.mjs +52 -0
  195. package/dist/plugins/admin/admin.d.mts +911 -0
  196. package/dist/plugins/admin/admin.mjs +89 -0
  197. package/dist/plugins/admin/client.d.mts +81 -0
  198. package/dist/plugins/admin/client.mjs +39 -0
  199. package/dist/plugins/admin/error-codes.d.mts +30 -0
  200. package/dist/plugins/admin/error-codes.mjs +29 -0
  201. package/dist/plugins/admin/has-permission.mjs +12 -0
  202. package/dist/plugins/admin/index.d.mts +3 -0
  203. package/dist/plugins/admin/index.mjs +2 -0
  204. package/dist/plugins/admin/routes.mjs +919 -0
  205. package/dist/plugins/admin/schema.d.mts +40 -0
  206. package/dist/plugins/admin/schema.mjs +33 -0
  207. package/dist/plugins/admin/types.d.mts +88 -0
  208. package/dist/plugins/anonymous/client.d.mts +32 -0
  209. package/dist/plugins/anonymous/client.mjs +21 -0
  210. package/dist/plugins/anonymous/error-codes.d.mts +15 -0
  211. package/dist/plugins/anonymous/error-codes.mjs +14 -0
  212. package/dist/plugins/anonymous/index.d.mts +175 -0
  213. package/dist/plugins/anonymous/index.mjs +219 -0
  214. package/dist/plugins/anonymous/schema.d.mts +15 -0
  215. package/dist/plugins/anonymous/schema.mjs +9 -0
  216. package/dist/plugins/anonymous/types.d.mts +65 -0
  217. package/dist/plugins/bearer/index.d.mts +45 -0
  218. package/dist/plugins/bearer/index.mjs +74 -0
  219. package/dist/plugins/captcha/constants.d.mts +9 -0
  220. package/dist/plugins/captcha/constants.mjs +27 -0
  221. package/dist/plugins/captcha/error-codes.mjs +13 -0
  222. package/dist/plugins/captcha/index.d.mts +27 -0
  223. package/dist/plugins/captcha/index.mjs +79 -0
  224. package/dist/plugins/captcha/types.d.mts +52 -0
  225. package/dist/plugins/captcha/utils.mjs +9 -0
  226. package/dist/plugins/captcha/verify-handlers/captchafox.mjs +27 -0
  227. package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +47 -0
  228. package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +32 -0
  229. package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +27 -0
  230. package/dist/plugins/custom-session/client.d.mts +17 -0
  231. package/dist/plugins/custom-session/client.mjs +7 -0
  232. package/dist/plugins/custom-session/index.d.mts +73 -0
  233. package/dist/plugins/custom-session/index.mjs +65 -0
  234. package/dist/plugins/device-authorization/client.d.mts +17 -0
  235. package/dist/plugins/device-authorization/client.mjs +18 -0
  236. package/dist/plugins/device-authorization/error-codes.mjs +19 -0
  237. package/dist/plugins/device-authorization/index.d.mts +558 -0
  238. package/dist/plugins/device-authorization/index.mjs +87 -0
  239. package/dist/plugins/device-authorization/routes.d.mts +32 -0
  240. package/dist/plugins/device-authorization/routes.mjs +725 -0
  241. package/dist/plugins/device-authorization/schema.d.mts +18 -0
  242. package/dist/plugins/device-authorization/schema.mjs +63 -0
  243. package/dist/plugins/email-otp/client.d.mts +21 -0
  244. package/dist/plugins/email-otp/client.mjs +17 -0
  245. package/dist/plugins/email-otp/error-codes.d.mts +10 -0
  246. package/dist/plugins/email-otp/error-codes.mjs +9 -0
  247. package/dist/plugins/email-otp/index.d.mts +551 -0
  248. package/dist/plugins/email-otp/index.mjs +145 -0
  249. package/dist/plugins/email-otp/otp-token.mjs +55 -0
  250. package/dist/plugins/email-otp/routes.mjs +784 -0
  251. package/dist/plugins/email-otp/types.d.mts +109 -0
  252. package/dist/plugins/email-otp/utils.mjs +17 -0
  253. package/dist/plugins/generic-oauth/error-codes.mjs +8 -0
  254. package/dist/plugins/generic-oauth/index.d.mts +52 -0
  255. package/dist/plugins/generic-oauth/index.mjs +279 -0
  256. package/dist/plugins/generic-oauth/providers/auth0.d.mts +36 -0
  257. package/dist/plugins/generic-oauth/providers/auth0.mjs +49 -0
  258. package/dist/plugins/generic-oauth/providers/gumroad.d.mts +31 -0
  259. package/dist/plugins/generic-oauth/providers/gumroad.mjs +62 -0
  260. package/dist/plugins/generic-oauth/providers/hubspot.d.mts +36 -0
  261. package/dist/plugins/generic-oauth/providers/hubspot.mjs +62 -0
  262. package/dist/plugins/generic-oauth/providers/index.d.mts +10 -0
  263. package/dist/plugins/generic-oauth/providers/keycloak.d.mts +36 -0
  264. package/dist/plugins/generic-oauth/providers/keycloak.mjs +47 -0
  265. package/dist/plugins/generic-oauth/providers/line.d.mts +54 -0
  266. package/dist/plugins/generic-oauth/providers/line.mjs +93 -0
  267. package/dist/plugins/generic-oauth/providers/microsoft-entra-id.d.mts +39 -0
  268. package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +104 -0
  269. package/dist/plugins/generic-oauth/providers/okta.d.mts +36 -0
  270. package/dist/plugins/generic-oauth/providers/okta.mjs +47 -0
  271. package/dist/plugins/generic-oauth/providers/patreon.d.mts +29 -0
  272. package/dist/plugins/generic-oauth/providers/patreon.mjs +61 -0
  273. package/dist/plugins/generic-oauth/providers/slack.d.mts +29 -0
  274. package/dist/plugins/generic-oauth/providers/slack.mjs +63 -0
  275. package/dist/plugins/generic-oauth/providers/yandex.d.mts +29 -0
  276. package/dist/plugins/generic-oauth/providers/yandex.mjs +67 -0
  277. package/dist/plugins/generic-oauth/types.d.mts +268 -0
  278. package/dist/plugins/haveibeenpwned/index.d.mts +63 -0
  279. package/dist/plugins/haveibeenpwned/index.mjs +81 -0
  280. package/dist/plugins/index.d.mts +69 -0
  281. package/dist/plugins/index.mjs +49 -0
  282. package/dist/plugins/jwt/adapter.mjs +68 -0
  283. package/dist/plugins/jwt/client.d.mts +41 -0
  284. package/dist/plugins/jwt/client.mjs +19 -0
  285. package/dist/plugins/jwt/cookie-cache.mjs +77 -0
  286. package/dist/plugins/jwt/index.d.mts +246 -0
  287. package/dist/plugins/jwt/index.mjs +214 -0
  288. package/dist/plugins/jwt/schema.d.mts +33 -0
  289. package/dist/plugins/jwt/schema.mjs +29 -0
  290. package/dist/plugins/jwt/sign.d.mts +128 -0
  291. package/dist/plugins/jwt/sign.mjs +130 -0
  292. package/dist/plugins/jwt/types.d.mts +256 -0
  293. package/dist/plugins/jwt/utils.d.mts +41 -0
  294. package/dist/plugins/jwt/utils.mjs +64 -0
  295. package/dist/plugins/jwt/verify.d.mts +11 -0
  296. package/dist/plugins/jwt/verify.mjs +45 -0
  297. package/dist/plugins/last-login-method/client.d.mts +48 -0
  298. package/dist/plugins/last-login-method/client.mjs +48 -0
  299. package/dist/plugins/last-login-method/index.d.mts +127 -0
  300. package/dist/plugins/last-login-method/index.mjs +98 -0
  301. package/dist/plugins/magic-link/client.d.mts +10 -0
  302. package/dist/plugins/magic-link/client.mjs +11 -0
  303. package/dist/plugins/magic-link/index.d.mts +213 -0
  304. package/dist/plugins/magic-link/index.mjs +208 -0
  305. package/dist/plugins/magic-link/utils.mjs +9 -0
  306. package/dist/plugins/multi-session/client.d.mts +19 -0
  307. package/dist/plugins/multi-session/client.mjs +19 -0
  308. package/dist/plugins/multi-session/error-codes.d.mts +8 -0
  309. package/dist/plugins/multi-session/error-codes.mjs +5 -0
  310. package/dist/plugins/multi-session/index.d.mts +212 -0
  311. package/dist/plugins/multi-session/index.mjs +217 -0
  312. package/dist/plugins/oauth-popup/client.d.mts +82 -0
  313. package/dist/plugins/oauth-popup/client.mjs +203 -0
  314. package/dist/plugins/oauth-popup/constants.d.mts +11 -0
  315. package/dist/plugins/oauth-popup/constants.mjs +11 -0
  316. package/dist/plugins/oauth-popup/error-codes.d.mts +11 -0
  317. package/dist/plugins/oauth-popup/error-codes.mjs +10 -0
  318. package/dist/plugins/oauth-popup/index.d.mts +67 -0
  319. package/dist/plugins/oauth-popup/index.mjs +232 -0
  320. package/dist/plugins/oauth-popup/types.d.mts +30 -0
  321. package/dist/plugins/oauth-proxy/index.d.mts +130 -0
  322. package/dist/plugins/oauth-proxy/index.mjs +407 -0
  323. package/dist/plugins/oauth-proxy/utils.mjs +55 -0
  324. package/dist/plugins/one-tap/client.d.mts +174 -0
  325. package/dist/plugins/one-tap/client.mjs +208 -0
  326. package/dist/plugins/one-tap/index.d.mts +82 -0
  327. package/dist/plugins/one-tap/index.mjs +100 -0
  328. package/dist/plugins/one-time-token/client.d.mts +10 -0
  329. package/dist/plugins/one-time-token/client.mjs +11 -0
  330. package/dist/plugins/one-time-token/index.d.mts +132 -0
  331. package/dist/plugins/one-time-token/index.mjs +107 -0
  332. package/dist/plugins/one-time-token/utils.mjs +9 -0
  333. package/dist/plugins/open-api/generator.d.mts +126 -0
  334. package/dist/plugins/open-api/generator.mjs +557 -0
  335. package/dist/plugins/open-api/index.d.mts +97 -0
  336. package/dist/plugins/open-api/index.mjs +65 -0
  337. package/dist/plugins/open-api/logo.mjs +13 -0
  338. package/dist/plugins/organization/access/index.d.mts +2 -0
  339. package/dist/plugins/organization/access/index.mjs +2 -0
  340. package/dist/plugins/organization/access/statement.d.mts +113 -0
  341. package/dist/plugins/organization/access/statement.mjs +77 -0
  342. package/dist/plugins/organization/adapter.d.mts +815 -0
  343. package/dist/plugins/organization/adapter.mjs +813 -0
  344. package/dist/plugins/organization/call.mjs +15 -0
  345. package/dist/plugins/organization/client.d.mts +375 -0
  346. package/dist/plugins/organization/client.mjs +104 -0
  347. package/dist/plugins/organization/error-codes.d.mts +66 -0
  348. package/dist/plugins/organization/error-codes.mjs +65 -0
  349. package/dist/plugins/organization/has-permission.d.mts +17 -0
  350. package/dist/plugins/organization/has-permission.mjs +34 -0
  351. package/dist/plugins/organization/index.d.mts +6 -0
  352. package/dist/plugins/organization/index.mjs +4 -0
  353. package/dist/plugins/organization/organization.d.mts +420 -0
  354. package/dist/plugins/organization/organization.mjs +886 -0
  355. package/dist/plugins/organization/permission.d.mts +15 -0
  356. package/dist/plugins/organization/permission.mjs +14 -0
  357. package/dist/plugins/organization/routes/crud-access-control.d.mts +511 -0
  358. package/dist/plugins/organization/routes/crud-access-control.mjs +674 -0
  359. package/dist/plugins/organization/routes/crud-invites.d.mts +1154 -0
  360. package/dist/plugins/organization/routes/crud-invites.mjs +602 -0
  361. package/dist/plugins/organization/routes/crud-members.d.mts +1057 -0
  362. package/dist/plugins/organization/routes/crud-members.mjs +518 -0
  363. package/dist/plugins/organization/routes/crud-org.d.mts +918 -0
  364. package/dist/plugins/organization/routes/crud-org.mjs +455 -0
  365. package/dist/plugins/organization/routes/crud-team.d.mts +1238 -0
  366. package/dist/plugins/organization/routes/crud-team.mjs +766 -0
  367. package/dist/plugins/organization/schema.d.mts +390 -0
  368. package/dist/plugins/organization/schema.mjs +65 -0
  369. package/dist/plugins/organization/types.d.mts +691 -0
  370. package/dist/plugins/phone-number/client.d.mts +31 -0
  371. package/dist/plugins/phone-number/client.mjs +19 -0
  372. package/dist/plugins/phone-number/error-codes.d.mts +19 -0
  373. package/dist/plugins/phone-number/error-codes.mjs +18 -0
  374. package/dist/plugins/phone-number/index.d.mts +360 -0
  375. package/dist/plugins/phone-number/index.mjs +57 -0
  376. package/dist/plugins/phone-number/routes.mjs +529 -0
  377. package/dist/plugins/phone-number/schema.d.mts +22 -0
  378. package/dist/plugins/phone-number/schema.mjs +18 -0
  379. package/dist/plugins/phone-number/types.d.mts +116 -0
  380. package/dist/plugins/siwe/client.d.mts +14 -0
  381. package/dist/plugins/siwe/client.mjs +15 -0
  382. package/dist/plugins/siwe/index.d.mts +62 -0
  383. package/dist/plugins/siwe/index.mjs +272 -0
  384. package/dist/plugins/siwe/parse-message.mjs +60 -0
  385. package/dist/plugins/siwe/schema.d.mts +35 -0
  386. package/dist/plugins/siwe/schema.mjs +30 -0
  387. package/dist/plugins/siwe/types.d.mts +43 -0
  388. package/dist/plugins/test-utils/auth-helpers.mjs +33 -0
  389. package/dist/plugins/test-utils/cookie-builder.mjs +55 -0
  390. package/dist/plugins/test-utils/db-helpers.mjs +65 -0
  391. package/dist/plugins/test-utils/factories.mjs +38 -0
  392. package/dist/plugins/test-utils/index.d.mts +73 -0
  393. package/dist/plugins/test-utils/index.mjs +97 -0
  394. package/dist/plugins/test-utils/otp-sink.mjs +21 -0
  395. package/dist/plugins/test-utils/types.d.mts +51 -0
  396. package/dist/plugins/two-factor/backup-codes/index.d.mts +291 -0
  397. package/dist/plugins/two-factor/backup-codes/index.mjs +341 -0
  398. package/dist/plugins/two-factor/client.d.mts +76 -0
  399. package/dist/plugins/two-factor/client.mjs +41 -0
  400. package/dist/plugins/two-factor/constant.mjs +6 -0
  401. package/dist/plugins/two-factor/error-code.d.mts +20 -0
  402. package/dist/plugins/two-factor/error-code.mjs +19 -0
  403. package/dist/plugins/two-factor/index.d.mts +720 -0
  404. package/dist/plugins/two-factor/index.mjs +349 -0
  405. package/dist/plugins/two-factor/otp/index.d.mts +216 -0
  406. package/dist/plugins/two-factor/otp/index.mjs +252 -0
  407. package/dist/plugins/two-factor/schema.d.mts +59 -0
  408. package/dist/plugins/two-factor/schema.mjs +53 -0
  409. package/dist/plugins/two-factor/totp/index.d.mts +219 -0
  410. package/dist/plugins/two-factor/totp/index.mjs +230 -0
  411. package/dist/plugins/two-factor/types.d.mts +111 -0
  412. package/dist/plugins/two-factor/utils.mjs +9 -0
  413. package/dist/plugins/two-factor/verify-two-factor.mjs +205 -0
  414. package/dist/plugins/username/client.d.mts +38 -0
  415. package/dist/plugins/username/client.mjs +17 -0
  416. package/dist/plugins/username/error-codes.d.mts +16 -0
  417. package/dist/plugins/username/error-codes.mjs +15 -0
  418. package/dist/plugins/username/index.d.mts +326 -0
  419. package/dist/plugins/username/index.mjs +312 -0
  420. package/dist/plugins/username/schema.d.mts +50 -0
  421. package/dist/plugins/username/schema.mjs +25 -0
  422. package/dist/social-providers/index.d.mts +1 -0
  423. package/dist/social-providers/index.mjs +2 -0
  424. package/dist/state.d.mts +48 -0
  425. package/dist/state.mjs +149 -0
  426. package/dist/test-utils/headers.d.mts +8 -0
  427. package/dist/test-utils/headers.mjs +17 -0
  428. package/dist/test-utils/http-test-instance.d.mts +413 -0
  429. package/dist/test-utils/http-test-instance.mjs +107 -0
  430. package/dist/test-utils/index.d.mts +4 -0
  431. package/dist/test-utils/index.mjs +4 -0
  432. package/dist/test-utils/test-instance.d.mts +56 -0
  433. package/dist/test-utils/test-instance.mjs +242 -0
  434. package/dist/types/adapter.d.mts +2 -0
  435. package/dist/types/api.d.mts +28 -0
  436. package/dist/types/auth.d.mts +32 -0
  437. package/dist/types/helper.d.mts +26 -0
  438. package/dist/types/index.d.mts +10 -0
  439. package/dist/types/index.mjs +1 -0
  440. package/dist/types/models.d.mts +10 -0
  441. package/dist/types/plugins.d.mts +19 -0
  442. package/dist/utils/boolean.mjs +6 -0
  443. package/dist/utils/constants.mjs +4 -0
  444. package/dist/utils/date.mjs +6 -0
  445. package/dist/utils/hashing.mjs +18 -0
  446. package/dist/utils/hide-metadata.d.mts +6 -0
  447. package/dist/utils/hide-metadata.mjs +4 -0
  448. package/dist/utils/index.d.mts +4 -0
  449. package/dist/utils/is-api-error.d.mts +2 -0
  450. package/dist/utils/is-api-error.mjs +2 -0
  451. package/dist/utils/is-atom.mjs +6 -0
  452. package/dist/utils/is-promise.mjs +6 -0
  453. package/dist/utils/middleware-response.mjs +7 -0
  454. package/dist/utils/password.mjs +32 -0
  455. package/dist/utils/plugin-helper.mjs +14 -0
  456. package/dist/utils/request.mjs +23 -0
  457. package/dist/utils/shim.mjs +22 -0
  458. package/dist/utils/time.d.mts +48 -0
  459. package/dist/utils/time.mjs +98 -0
  460. package/dist/utils/url.d.mts +78 -0
  461. package/dist/utils/url.mjs +238 -0
  462. package/dist/utils/validate-user-info.mjs +44 -0
  463. package/dist/utils/wildcard.mjs +106 -0
  464. package/dist/version.mjs +5 -0
  465. package/package.json +595 -3
@@ -0,0 +1,725 @@
1
+ import { ms } from "../../utils/time.mjs";
2
+ import { generateRandomString } from "../../crypto/random.mjs";
3
+ import { getSessionFromCtx } from "../../api/routes/session.mjs";
4
+ import { DEVICE_AUTHORIZATION_ERROR_CODES } from "./error-codes.mjs";
5
+ import { APIError } from "@better-auth/core/error";
6
+ import { createAuthEndpoint } from "@better-auth/core/api";
7
+ import * as z from "zod";
8
+ //#region src/plugins/device-authorization/routes.ts
9
+ const defaultCharset = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
10
+ const MAX_DEVICE_CODE_GENERATION_ATTEMPTS = 3;
11
+ const UNIQUE_CONSTRAINT_ERROR_IDENTIFIERS = new Set([
12
+ "11000",
13
+ "1062",
14
+ "2067",
15
+ "23505",
16
+ "2601",
17
+ "2627",
18
+ "ER_DUP_ENTRY",
19
+ "P2002",
20
+ "SQLITE_CONSTRAINT_UNIQUE"
21
+ ]);
22
+ function isUniqueConstraintError(error) {
23
+ if (typeof error !== "object" || error === null) return false;
24
+ const details = error;
25
+ if ([
26
+ details.code,
27
+ details.errcode,
28
+ details.errno,
29
+ details.number
30
+ ].some((identifier) => UNIQUE_CONSTRAINT_ERROR_IDENTIFIERS.has(String(identifier)))) return true;
31
+ const message = details.message;
32
+ return typeof message === "string" && /unique(?: key)? constraint|duplicate (?:entry|key)|e11000/i.test(message);
33
+ }
34
+ const defaultUserCodePattern = new RegExp(`^[${defaultCharset}]+$`, "i");
35
+ function validateGeneratedCode(code, label) {
36
+ if (typeof code !== "string") throw new APIError("BAD_REQUEST", {
37
+ error: "invalid_request",
38
+ error_description: `Generated ${label} code must be a string`
39
+ });
40
+ if (Array.from(code).length > 191) throw new APIError("BAD_REQUEST", {
41
+ error: "invalid_request",
42
+ error_description: `Generated ${label} code must be at most 191 characters`
43
+ });
44
+ return code;
45
+ }
46
+ function normalizeUserCode(userCode) {
47
+ return userCode.replace(/[^a-zA-Z0-9]/g, "").toUpperCase();
48
+ }
49
+ /**
50
+ * Preserve exact custom user codes, and normalize only default-alphabet codes.
51
+ */
52
+ async function findDeviceCodeByUserCode(ctx, userCode) {
53
+ const findByUserCode = async (value) => {
54
+ const deviceCode = await ctx.context.adapter.findOne({
55
+ model: "deviceCode",
56
+ where: [{
57
+ field: "userCode",
58
+ value
59
+ }]
60
+ });
61
+ return deviceCode?.userCode === value ? deviceCode : null;
62
+ };
63
+ const exactDeviceCode = await findByUserCode(userCode);
64
+ if (exactDeviceCode) return exactDeviceCode;
65
+ const normalizedUserCode = normalizeUserCode(userCode);
66
+ if (normalizedUserCode === userCode || !defaultUserCodePattern.test(normalizedUserCode)) return exactDeviceCode;
67
+ return findByUserCode(normalizedUserCode);
68
+ }
69
+ const deviceCodeBodySchema = z.object({
70
+ client_id: z.string().meta({ description: "The client ID of the application" }),
71
+ user_id: z.string().meta({ description: "The user ID to which the device code should be pre-bound." }).optional(),
72
+ scope: z.string().meta({ description: "Space-separated list of scopes" }).optional()
73
+ });
74
+ const deviceCodeBaseErrorCodes = [
75
+ "invalid_request",
76
+ "invalid_client",
77
+ "unauthorized_client",
78
+ "invalid_scope"
79
+ ];
80
+ const deviceAuthorizationBaseRequestFields = [
81
+ "client_id",
82
+ "user_id",
83
+ "scope"
84
+ ];
85
+ async function normalizeDeviceAuthorizationBaseRequestParameters(request, body) {
86
+ for (const field of deviceAuthorizationBaseRequestFields) if (body[field] === "") body[field] = void 0;
87
+ const contentType = request?.headers.get("content-type")?.toLowerCase() ?? "";
88
+ if (!request || !contentType.includes("application/x-www-form-urlencoded")) return;
89
+ const params = new URLSearchParams(await request.clone().text());
90
+ for (const field of deviceAuthorizationBaseRequestFields) {
91
+ const effectiveValues = params.getAll(field).filter((value) => value.length > 0);
92
+ if (effectiveValues.length > 1) throw new APIError("BAD_REQUEST", {
93
+ error: "invalid_request",
94
+ error_description: `${field} must not be repeated`
95
+ });
96
+ if (effectiveValues.length === 0) body[field] = void 0;
97
+ else body[field] = effectiveValues[0];
98
+ }
99
+ }
100
+ const deviceCode = (opts, grant) => {
101
+ const generateDeviceCode = async () => {
102
+ return validateGeneratedCode(opts.generateDeviceCode ? await opts.generateDeviceCode() : defaultGenerateDeviceCode(opts.deviceCodeLength), "device");
103
+ };
104
+ const generateUserCode = async () => {
105
+ return validateGeneratedCode(opts.generateUserCode ? await opts.generateUserCode() : defaultGenerateUserCode(opts.userCodeLength), "user");
106
+ };
107
+ const requestFields = grant?.requestSchemaFields ?? {};
108
+ const requestSchema = (grant ? deviceCodeBodySchema.extend({ client_id: z.string().optional() }) : deviceCodeBodySchema).extend(requestFields);
109
+ const requestErrorCodes = [...deviceCodeBaseErrorCodes, ...grant?.requestErrorCodes ?? []];
110
+ const endpointErrorCodes = [...requestErrorCodes, "server_error"];
111
+ return createAuthEndpoint("/device/code", {
112
+ method: "POST",
113
+ cloneRequest: true,
114
+ body: requestSchema,
115
+ error: z.object({
116
+ error: z.enum(endpointErrorCodes).meta({ description: "Error code" }),
117
+ error_description: z.string().meta({ description: "Detailed error description" })
118
+ }),
119
+ onValidationError: ({ issues, message }) => {
120
+ grant?.onRequestValidationError?.(issues);
121
+ throw new APIError("BAD_REQUEST", {
122
+ error: "invalid_request",
123
+ error_description: message
124
+ });
125
+ },
126
+ metadata: {
127
+ noStore: true,
128
+ allowedMediaTypes: ["application/json", "application/x-www-form-urlencoded"],
129
+ openapi: {
130
+ description: `Request a device and user code
131
+
132
+ Follow [rfc8628#section-3.2](https://datatracker.ietf.org/doc/html/rfc8628#section-3.2)`,
133
+ responses: {
134
+ ...grant?.requestOpenAPIResponses,
135
+ 200: {
136
+ description: "Success",
137
+ content: { "application/json": { schema: {
138
+ type: "object",
139
+ properties: {
140
+ device_code: {
141
+ type: "string",
142
+ description: "The device verification code"
143
+ },
144
+ user_code: {
145
+ type: "string",
146
+ description: "The user code to display"
147
+ },
148
+ verification_uri: {
149
+ type: "string",
150
+ format: "uri",
151
+ description: "The URL for user verification. Defaults to /device if not configured."
152
+ },
153
+ verification_uri_complete: {
154
+ type: "string",
155
+ format: "uri",
156
+ description: "The complete URL with user code as query parameter."
157
+ },
158
+ expires_in: {
159
+ type: "number",
160
+ description: "Lifetime in seconds of the device code"
161
+ },
162
+ interval: {
163
+ type: "number",
164
+ description: "Minimum polling interval in seconds"
165
+ }
166
+ }
167
+ } } }
168
+ },
169
+ 400: {
170
+ description: "Error response",
171
+ content: { "application/json": { schema: {
172
+ type: "object",
173
+ properties: {
174
+ error: {
175
+ type: "string",
176
+ enum: requestErrorCodes
177
+ },
178
+ error_description: { type: "string" }
179
+ }
180
+ } } }
181
+ },
182
+ 500: {
183
+ description: "Server error",
184
+ content: { "application/json": { schema: {
185
+ type: "object",
186
+ properties: {
187
+ error: {
188
+ type: "string",
189
+ enum: ["server_error"]
190
+ },
191
+ error_description: { type: "string" }
192
+ }
193
+ } } }
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }, async (ctx) => {
199
+ const request = ctx.body;
200
+ await normalizeDeviceAuthorizationBaseRequestParameters(ctx.request, request);
201
+ const grantAuthorization = grant ? await grant.authorizeRequest({
202
+ ctx,
203
+ request
204
+ }) : void 0;
205
+ const clientId = grantAuthorization?.clientId ?? request.client_id;
206
+ if (!grantAuthorization) {
207
+ if (!request.client_id) throw new APIError("BAD_REQUEST", {
208
+ error: "invalid_request",
209
+ error_description: "client_id is required"
210
+ });
211
+ if (!opts.validateClient) {
212
+ if (grant) throw new APIError("BAD_REQUEST", {
213
+ error: "invalid_client",
214
+ error_description: "Invalid client ID"
215
+ });
216
+ } else if (!await opts.validateClient(request.client_id)) throw new APIError("BAD_REQUEST", {
217
+ error: "invalid_client",
218
+ error_description: "Invalid client ID"
219
+ });
220
+ }
221
+ if (!clientId) throw new APIError("BAD_REQUEST", {
222
+ error: "invalid_request",
223
+ error_description: "client_id is required"
224
+ });
225
+ if (opts.onDeviceAuthRequest) await opts.onDeviceAuthRequest(clientId, request.scope);
226
+ const expiresIn = ms(opts.expiresIn);
227
+ const expiresAt = new Date(Date.now() + expiresIn);
228
+ for (let attempt = 0; attempt < MAX_DEVICE_CODE_GENERATION_ATTEMPTS; attempt++) {
229
+ const deviceCode = await generateDeviceCode();
230
+ const userCode = await generateUserCode();
231
+ try {
232
+ await ctx.context.adapter.create({
233
+ model: "deviceCode",
234
+ data: {
235
+ ...grantAuthorization?.deviceCodeFields,
236
+ deviceCode,
237
+ userCode,
238
+ userId: request.user_id || null,
239
+ expiresAt,
240
+ status: "pending",
241
+ pollingInterval: ms(opts.interval),
242
+ clientId,
243
+ scope: request.scope
244
+ }
245
+ });
246
+ } catch (error) {
247
+ if (!isUniqueConstraintError(error)) throw error;
248
+ continue;
249
+ }
250
+ const { verificationUri, verificationUriComplete } = buildVerificationUris(opts.verificationUri, ctx.context.baseURL, userCode);
251
+ ctx.setHeader("Cache-Control", "no-store");
252
+ ctx.setHeader("Pragma", "no-cache");
253
+ return ctx.json({
254
+ device_code: deviceCode,
255
+ user_code: userCode,
256
+ verification_uri: verificationUri,
257
+ verification_uri_complete: verificationUriComplete,
258
+ expires_in: Math.floor(expiresIn / 1e3),
259
+ interval: Math.floor(ms(opts.interval) / 1e3)
260
+ });
261
+ }
262
+ throw new APIError("INTERNAL_SERVER_ERROR", {
263
+ error: "server_error",
264
+ error_description: "Failed to generate a unique device code"
265
+ });
266
+ });
267
+ };
268
+ const deviceTokenBodySchema = z.object({
269
+ grant_type: z.literal("urn:ietf:params:oauth:grant-type:device_code").meta({ description: "The grant type for device flow" }),
270
+ device_code: z.string().meta({ description: "The device verification code" }),
271
+ client_id: z.string().meta({ description: "The client ID of the application" })
272
+ });
273
+ const deviceTokenErrorSchema = z.object({
274
+ error: z.enum([
275
+ "authorization_pending",
276
+ "slow_down",
277
+ "expired_token",
278
+ "access_denied",
279
+ "invalid_request",
280
+ "invalid_grant"
281
+ ]).meta({ description: "Error code" }),
282
+ error_description: z.string().meta({ description: "Detailed error description" })
283
+ });
284
+ /**
285
+ * Runs the RFC 8628 polling and one-time claim state machine shared by every
286
+ * token issuer. Issuers supply ownership checks and grant-specific validation,
287
+ * but cannot bypass expiry, polling, denial, or atomic consumption.
288
+ */
289
+ async function redeemDeviceCode(input) {
290
+ const deviceCodeRecord = await input.ctx.context.adapter.findOne({
291
+ model: "deviceCode",
292
+ where: [{
293
+ field: "deviceCode",
294
+ value: input.deviceCode
295
+ }]
296
+ });
297
+ if (!deviceCodeRecord) throw new APIError("BAD_REQUEST", {
298
+ error: "invalid_grant",
299
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_DEVICE_CODE.message
300
+ });
301
+ const authorization = await input.authorizeRedemption(deviceCodeRecord);
302
+ if (deviceCodeRecord.lastPolledAt && deviceCodeRecord.pollingInterval) {
303
+ if (Date.now() - new Date(deviceCodeRecord.lastPolledAt).getTime() < deviceCodeRecord.pollingInterval) throw new APIError("BAD_REQUEST", {
304
+ error: "slow_down",
305
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.POLLING_TOO_FREQUENTLY.message
306
+ });
307
+ }
308
+ await input.ctx.context.adapter.update({
309
+ model: "deviceCode",
310
+ where: [{
311
+ field: "id",
312
+ value: deviceCodeRecord.id
313
+ }],
314
+ update: { lastPolledAt: /* @__PURE__ */ new Date() }
315
+ });
316
+ if (deviceCodeRecord.expiresAt < /* @__PURE__ */ new Date()) {
317
+ await input.ctx.context.adapter.delete({
318
+ model: "deviceCode",
319
+ where: [{
320
+ field: "id",
321
+ value: deviceCodeRecord.id
322
+ }]
323
+ });
324
+ throw new APIError("BAD_REQUEST", {
325
+ error: "expired_token",
326
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.EXPIRED_DEVICE_CODE.message
327
+ });
328
+ }
329
+ if (deviceCodeRecord.status === "pending") throw new APIError("BAD_REQUEST", {
330
+ error: "authorization_pending",
331
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.AUTHORIZATION_PENDING.message
332
+ });
333
+ if (deviceCodeRecord.status === "denied") {
334
+ await input.ctx.context.adapter.delete({
335
+ model: "deviceCode",
336
+ where: [{
337
+ field: "id",
338
+ value: deviceCodeRecord.id
339
+ }]
340
+ });
341
+ throw new APIError("BAD_REQUEST", {
342
+ error: "access_denied",
343
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.ACCESS_DENIED.message
344
+ });
345
+ }
346
+ if (deviceCodeRecord.status !== "approved" || !deviceCodeRecord.userId) throw new APIError("INTERNAL_SERVER_ERROR", {
347
+ error: "server_error",
348
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_DEVICE_CODE_STATUS.message
349
+ });
350
+ const redemptionContext = await input.prepareRedemption(deviceCodeRecord, authorization.context);
351
+ const user = await input.ctx.context.internalAdapter.findUserById(deviceCodeRecord.userId);
352
+ if (!user) throw new APIError("INTERNAL_SERVER_ERROR", {
353
+ error: "server_error",
354
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.USER_NOT_FOUND.message
355
+ });
356
+ const claimedDeviceCode = await input.ctx.context.adapter.consumeOne({
357
+ model: "deviceCode",
358
+ where: [
359
+ {
360
+ field: "id",
361
+ value: deviceCodeRecord.id
362
+ },
363
+ authorization.ownershipWhere,
364
+ {
365
+ field: "status",
366
+ value: "approved"
367
+ }
368
+ ]
369
+ });
370
+ if (!claimedDeviceCode?.userId) throw new APIError("BAD_REQUEST", {
371
+ error: "invalid_grant",
372
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_DEVICE_CODE.message
373
+ });
374
+ return {
375
+ claimedDeviceCode,
376
+ authorizationContext: authorization.context,
377
+ redemptionContext,
378
+ user
379
+ };
380
+ }
381
+ const deviceToken = (opts, grant) => createAuthEndpoint("/device/token", {
382
+ method: "POST",
383
+ body: deviceTokenBodySchema,
384
+ error: deviceTokenErrorSchema,
385
+ metadata: {
386
+ noStore: true,
387
+ openapi: {
388
+ description: `Exchange device code for access token
389
+
390
+ Follow [rfc8628#section-3.4](https://datatracker.ietf.org/doc/html/rfc8628#section-3.4)`,
391
+ responses: {
392
+ 200: {
393
+ description: "Success",
394
+ content: { "application/json": { schema: {
395
+ type: "object",
396
+ properties: {
397
+ session: { $ref: "#/components/schemas/Session" },
398
+ user: { $ref: "#/components/schemas/User" }
399
+ }
400
+ } } }
401
+ },
402
+ 400: {
403
+ description: "Error response",
404
+ content: { "application/json": { schema: {
405
+ type: "object",
406
+ properties: {
407
+ error: {
408
+ type: "string",
409
+ enum: [
410
+ "authorization_pending",
411
+ "slow_down",
412
+ "expired_token",
413
+ "access_denied",
414
+ "invalid_request",
415
+ "invalid_grant"
416
+ ]
417
+ },
418
+ error_description: { type: "string" }
419
+ }
420
+ } } }
421
+ }
422
+ }
423
+ }
424
+ }
425
+ }, async (ctx) => {
426
+ const { device_code, client_id } = ctx.body;
427
+ if (opts.validateClient) {
428
+ if (!await opts.validateClient(client_id)) throw new APIError("BAD_REQUEST", {
429
+ error: "invalid_grant",
430
+ error_description: "Invalid client ID"
431
+ });
432
+ }
433
+ const { claimedDeviceCode, user } = await redeemDeviceCode({
434
+ ctx,
435
+ deviceCode: device_code,
436
+ authorizeRedemption: async (deviceCodeRecord) => {
437
+ if (deviceCodeRecord.clientId && deviceCodeRecord.clientId !== client_id) throw new APIError("BAD_REQUEST", {
438
+ error: "invalid_grant",
439
+ error_description: "Client ID mismatch"
440
+ });
441
+ await grant?.assertSessionRedemption({
442
+ ctx,
443
+ deviceCode: deviceCodeRecord
444
+ });
445
+ return {
446
+ ownershipWhere: {
447
+ field: "clientId",
448
+ value: client_id
449
+ },
450
+ context: void 0
451
+ };
452
+ },
453
+ prepareRedemption: () => void 0
454
+ });
455
+ const session = await ctx.context.internalAdapter.createSession(user.id);
456
+ if (!session) throw new APIError("INTERNAL_SERVER_ERROR", {
457
+ error: "server_error",
458
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.FAILED_TO_CREATE_SESSION.message
459
+ });
460
+ ctx.context.setNewSession({
461
+ session,
462
+ user
463
+ });
464
+ if (ctx.context.options.secondaryStorage) await ctx.context.secondaryStorage?.set(session.token, JSON.stringify({
465
+ user,
466
+ session
467
+ }), Math.floor((new Date(session.expiresAt).getTime() - Date.now()) / 1e3));
468
+ ctx.setHeader("Cache-Control", "no-store");
469
+ ctx.setHeader("Pragma", "no-cache");
470
+ return ctx.json({
471
+ access_token: session.token,
472
+ token_type: "Bearer",
473
+ expires_in: Math.floor((new Date(session.expiresAt).getTime() - Date.now()) / 1e3),
474
+ scope: claimedDeviceCode.scope || ""
475
+ });
476
+ });
477
+ const deviceVerify = (grant) => createAuthEndpoint("/device", {
478
+ method: "GET",
479
+ query: z.object({ user_code: z.string().meta({ description: "The user code to verify" }) }),
480
+ error: z.object({
481
+ error: z.enum(["invalid_request"]).meta({ description: "Error code" }),
482
+ error_description: z.string().meta({ description: "Detailed error description" })
483
+ }),
484
+ metadata: { openapi: {
485
+ description: "Verify user code and get device authorization status",
486
+ responses: { 200: {
487
+ description: "Device authorization status",
488
+ content: { "application/json": { schema: {
489
+ type: "object",
490
+ properties: {
491
+ user_code: {
492
+ type: "string",
493
+ description: "The user code to verify"
494
+ },
495
+ status: {
496
+ type: "string",
497
+ enum: [
498
+ "pending",
499
+ "approved",
500
+ "denied"
501
+ ],
502
+ description: "Current status of the device authorization"
503
+ },
504
+ client_id: {
505
+ type: "string",
506
+ description: "The client requesting authorization, returned only to the authenticated user who owns this request"
507
+ },
508
+ scope: {
509
+ type: "string",
510
+ description: "The requested scopes, returned only to the authenticated user who owns this request"
511
+ },
512
+ ...grant?.verificationOpenAPIProperties
513
+ }
514
+ } } }
515
+ } }
516
+ } }
517
+ }, async (ctx) => {
518
+ const { user_code } = ctx.query;
519
+ const deviceCodeRecord = await findDeviceCodeByUserCode(ctx, user_code);
520
+ if (!deviceCodeRecord) throw new APIError("BAD_REQUEST", {
521
+ error: "invalid_request",
522
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_USER_CODE.message
523
+ });
524
+ if (deviceCodeRecord.expiresAt < /* @__PURE__ */ new Date()) throw new APIError("BAD_REQUEST", {
525
+ error: "expired_token",
526
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.EXPIRED_USER_CODE.message
527
+ });
528
+ const session = await getSessionFromCtx(ctx);
529
+ if (session?.user?.id && !deviceCodeRecord.userId && deviceCodeRecord.status === "pending") {
530
+ if (await ctx.context.adapter.incrementOne({
531
+ model: "deviceCode",
532
+ where: [
533
+ {
534
+ field: "id",
535
+ value: deviceCodeRecord.id
536
+ },
537
+ {
538
+ field: "status",
539
+ value: "pending"
540
+ },
541
+ {
542
+ field: "userId",
543
+ operator: "eq",
544
+ value: null
545
+ }
546
+ ],
547
+ increment: {},
548
+ set: { userId: session.user.id }
549
+ })) deviceCodeRecord.userId = session.user.id;
550
+ }
551
+ const canReviewRequest = session?.user.id !== void 0 && deviceCodeRecord.userId === session.user.id;
552
+ const grantContext = canReviewRequest ? grant?.getVerificationContext(deviceCodeRecord) : void 0;
553
+ const response = {
554
+ ...canReviewRequest ? grantContext : void 0,
555
+ user_code,
556
+ status: deviceCodeRecord.status,
557
+ ...canReviewRequest ? {
558
+ client_id: deviceCodeRecord.clientId,
559
+ scope: deviceCodeRecord.scope
560
+ } : {}
561
+ };
562
+ return ctx.json(response);
563
+ });
564
+ const deviceApprove = createAuthEndpoint("/device/approve", {
565
+ method: "POST",
566
+ body: z.object({ userCode: z.string().meta({ description: "The user code to approve" }) }),
567
+ error: z.object({
568
+ error: z.enum([
569
+ "invalid_request",
570
+ "expired_token",
571
+ "device_code_already_processed",
572
+ "unauthorized",
573
+ "access_denied"
574
+ ]).meta({ description: "Error code" }),
575
+ error_description: z.string().meta({ description: "Detailed error description" })
576
+ }),
577
+ requireHeaders: true,
578
+ metadata: { openapi: {
579
+ description: "Approve device authorization",
580
+ responses: { 200: {
581
+ description: "Success",
582
+ content: { "application/json": { schema: {
583
+ type: "object",
584
+ properties: { success: { type: "boolean" } }
585
+ } } }
586
+ } }
587
+ } }
588
+ }, async (ctx) => {
589
+ const session = await getSessionFromCtx(ctx);
590
+ if (!session) throw new APIError("UNAUTHORIZED", {
591
+ error: "unauthorized",
592
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.AUTHENTICATION_REQUIRED.message
593
+ });
594
+ const { userCode } = ctx.body;
595
+ const deviceCodeRecord = await findDeviceCodeByUserCode(ctx, userCode);
596
+ if (!deviceCodeRecord) throw new APIError("BAD_REQUEST", {
597
+ error: "invalid_request",
598
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_USER_CODE.message
599
+ });
600
+ if (deviceCodeRecord.expiresAt < /* @__PURE__ */ new Date()) throw new APIError("BAD_REQUEST", {
601
+ error: "expired_token",
602
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.EXPIRED_USER_CODE.message
603
+ });
604
+ if (deviceCodeRecord.status !== "pending") throw new APIError("BAD_REQUEST", {
605
+ error: "invalid_request",
606
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.DEVICE_CODE_ALREADY_PROCESSED.message
607
+ });
608
+ if (!deviceCodeRecord.userId) throw new APIError("BAD_REQUEST", {
609
+ error: "invalid_request",
610
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.DEVICE_CODE_NOT_CLAIMED.message
611
+ });
612
+ if (deviceCodeRecord.userId !== session.user.id) throw new APIError("FORBIDDEN", {
613
+ error: "access_denied",
614
+ error_description: "You are not authorized to approve this device authorization"
615
+ });
616
+ await ctx.context.adapter.update({
617
+ model: "deviceCode",
618
+ where: [{
619
+ field: "id",
620
+ value: deviceCodeRecord.id
621
+ }],
622
+ update: {
623
+ status: "approved",
624
+ userId: session.user.id
625
+ }
626
+ });
627
+ return ctx.json({ success: true });
628
+ });
629
+ const deviceDeny = createAuthEndpoint("/device/deny", {
630
+ method: "POST",
631
+ body: z.object({ userCode: z.string().meta({ description: "The user code to deny" }) }),
632
+ error: z.object({
633
+ error: z.enum([
634
+ "invalid_request",
635
+ "expired_token",
636
+ "unauthorized",
637
+ "access_denied"
638
+ ]).meta({ description: "Error code" }),
639
+ error_description: z.string().meta({ description: "Detailed error description" })
640
+ }),
641
+ requireHeaders: true,
642
+ metadata: { openapi: {
643
+ description: "Deny device authorization",
644
+ responses: { 200: {
645
+ description: "Success",
646
+ content: { "application/json": { schema: {
647
+ type: "object",
648
+ properties: { success: { type: "boolean" } }
649
+ } } }
650
+ } }
651
+ } }
652
+ }, async (ctx) => {
653
+ const session = await getSessionFromCtx(ctx);
654
+ if (!session) throw new APIError("UNAUTHORIZED", {
655
+ error: "unauthorized",
656
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.AUTHENTICATION_REQUIRED.message
657
+ });
658
+ const { userCode } = ctx.body;
659
+ const deviceCodeRecord = await findDeviceCodeByUserCode(ctx, userCode);
660
+ if (!deviceCodeRecord) throw new APIError("BAD_REQUEST", {
661
+ error: "invalid_request",
662
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.INVALID_USER_CODE.message
663
+ });
664
+ if (deviceCodeRecord.expiresAt < /* @__PURE__ */ new Date()) throw new APIError("BAD_REQUEST", {
665
+ error: "expired_token",
666
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.EXPIRED_USER_CODE.message
667
+ });
668
+ if (deviceCodeRecord.status !== "pending") throw new APIError("BAD_REQUEST", {
669
+ error: "invalid_request",
670
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.DEVICE_CODE_ALREADY_PROCESSED.message
671
+ });
672
+ if (!deviceCodeRecord.userId) throw new APIError("BAD_REQUEST", {
673
+ error: "invalid_request",
674
+ error_description: DEVICE_AUTHORIZATION_ERROR_CODES.DEVICE_CODE_NOT_CLAIMED.message
675
+ });
676
+ if (deviceCodeRecord.userId !== session.user.id) throw new APIError("FORBIDDEN", {
677
+ error: "access_denied",
678
+ error_description: "You are not authorized to deny this device authorization"
679
+ });
680
+ await ctx.context.adapter.update({
681
+ model: "deviceCode",
682
+ where: [{
683
+ field: "id",
684
+ value: deviceCodeRecord.id
685
+ }],
686
+ update: {
687
+ status: "denied",
688
+ userId: session.user.id
689
+ }
690
+ });
691
+ return ctx.json({ success: true });
692
+ });
693
+ /**
694
+ * @internal
695
+ */
696
+ const buildVerificationUris = (verificationUri, baseURL, userCode) => {
697
+ const uri = verificationUri || "/device";
698
+ let verificationUrl;
699
+ try {
700
+ verificationUrl = new URL(uri);
701
+ } catch {
702
+ verificationUrl = new URL(uri, baseURL);
703
+ }
704
+ const verificationUriCompleteUrl = new URL(verificationUrl);
705
+ verificationUriCompleteUrl.searchParams.set("user_code", userCode);
706
+ return {
707
+ verificationUri: verificationUrl.toString(),
708
+ verificationUriComplete: verificationUriCompleteUrl.toString()
709
+ };
710
+ };
711
+ /**
712
+ * @internal
713
+ */
714
+ const defaultGenerateDeviceCode = (length) => {
715
+ return generateRandomString(length, "a-z", "A-Z", "0-9");
716
+ };
717
+ /**
718
+ * @internal
719
+ */
720
+ const defaultGenerateUserCode = (length) => {
721
+ const chars = new Uint8Array(length);
722
+ return Array.from(crypto.getRandomValues(chars)).map((byte) => defaultCharset[byte % 32]).join("");
723
+ };
724
+ //#endregion
725
+ export { deviceApprove, deviceCode, deviceDeny, deviceToken, deviceVerify, redeemDeviceCode };