@hammadj/better-auth-core 1.5.0-beta.9

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 (353) hide show
  1. package/.turbo/turbo-build.log +266 -0
  2. package/.turbo/turbo-test.log +2 -0
  3. package/LICENSE.md +20 -0
  4. package/dist/api/index.d.mts +181 -0
  5. package/dist/api/index.mjs +34 -0
  6. package/dist/api/index.mjs.map +1 -0
  7. package/dist/async_hooks/index.d.mts +7 -0
  8. package/dist/async_hooks/index.mjs +22 -0
  9. package/dist/async_hooks/index.mjs.map +1 -0
  10. package/dist/async_hooks/pure.index.d.mts +7 -0
  11. package/dist/async_hooks/pure.index.mjs +35 -0
  12. package/dist/async_hooks/pure.index.mjs.map +1 -0
  13. package/dist/context/endpoint-context.d.mts +19 -0
  14. package/dist/context/endpoint-context.mjs +32 -0
  15. package/dist/context/endpoint-context.mjs.map +1 -0
  16. package/dist/context/global.d.mts +7 -0
  17. package/dist/context/global.mjs +38 -0
  18. package/dist/context/global.mjs.map +1 -0
  19. package/dist/context/index.d.mts +5 -0
  20. package/dist/context/index.mjs +6 -0
  21. package/dist/context/request-state.d.mts +26 -0
  22. package/dist/context/request-state.mjs +50 -0
  23. package/dist/context/request-state.mjs.map +1 -0
  24. package/dist/context/transaction.d.mts +25 -0
  25. package/dist/context/transaction.mjs +96 -0
  26. package/dist/context/transaction.mjs.map +1 -0
  27. package/dist/db/adapter/factory.d.mts +28 -0
  28. package/dist/db/adapter/factory.mjs +716 -0
  29. package/dist/db/adapter/factory.mjs.map +1 -0
  30. package/dist/db/adapter/get-default-field-name.d.mts +19 -0
  31. package/dist/db/adapter/get-default-field-name.mjs +39 -0
  32. package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
  33. package/dist/db/adapter/get-default-model-name.d.mts +13 -0
  34. package/dist/db/adapter/get-default-model-name.mjs +33 -0
  35. package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
  36. package/dist/db/adapter/get-field-attributes.d.mts +30 -0
  37. package/dist/db/adapter/get-field-attributes.mjs +40 -0
  38. package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
  39. package/dist/db/adapter/get-field-name.d.mts +19 -0
  40. package/dist/db/adapter/get-field-name.mjs +34 -0
  41. package/dist/db/adapter/get-field-name.mjs.map +1 -0
  42. package/dist/db/adapter/get-id-field.d.mts +40 -0
  43. package/dist/db/adapter/get-id-field.mjs +68 -0
  44. package/dist/db/adapter/get-id-field.mjs.map +1 -0
  45. package/dist/db/adapter/get-model-name.d.mts +13 -0
  46. package/dist/db/adapter/get-model-name.mjs +24 -0
  47. package/dist/db/adapter/get-model-name.mjs.map +1 -0
  48. package/dist/db/adapter/index.d.mts +515 -0
  49. package/dist/db/adapter/index.mjs +10 -0
  50. package/dist/db/adapter/types.d.mts +140 -0
  51. package/dist/db/adapter/utils.d.mts +8 -0
  52. package/dist/db/adapter/utils.mjs +39 -0
  53. package/dist/db/adapter/utils.mjs.map +1 -0
  54. package/dist/db/get-tables.d.mts +9 -0
  55. package/dist/db/get-tables.mjs +267 -0
  56. package/dist/db/get-tables.mjs.map +1 -0
  57. package/dist/db/index.d.mts +10 -0
  58. package/dist/db/index.mjs +9 -0
  59. package/dist/db/plugin.d.mts +13 -0
  60. package/dist/db/schema/account.d.mts +27 -0
  61. package/dist/db/schema/account.mjs +20 -0
  62. package/dist/db/schema/account.mjs.map +1 -0
  63. package/dist/db/schema/rate-limit.d.mts +15 -0
  64. package/dist/db/schema/rate-limit.mjs +12 -0
  65. package/dist/db/schema/rate-limit.mjs.map +1 -0
  66. package/dist/db/schema/session.d.mts +22 -0
  67. package/dist/db/schema/session.mjs +15 -0
  68. package/dist/db/schema/session.mjs.map +1 -0
  69. package/dist/db/schema/shared.d.mts +11 -0
  70. package/dist/db/schema/shared.mjs +12 -0
  71. package/dist/db/schema/shared.mjs.map +1 -0
  72. package/dist/db/schema/user.d.mts +21 -0
  73. package/dist/db/schema/user.mjs +14 -0
  74. package/dist/db/schema/user.mjs.map +1 -0
  75. package/dist/db/schema/verification.d.mts +20 -0
  76. package/dist/db/schema/verification.mjs +13 -0
  77. package/dist/db/schema/verification.mjs.map +1 -0
  78. package/dist/db/type.d.mts +147 -0
  79. package/dist/env/color-depth.d.mts +5 -0
  80. package/dist/env/color-depth.mjs +89 -0
  81. package/dist/env/color-depth.mjs.map +1 -0
  82. package/dist/env/env-impl.d.mts +33 -0
  83. package/dist/env/env-impl.mjs +83 -0
  84. package/dist/env/env-impl.mjs.map +1 -0
  85. package/dist/env/index.d.mts +4 -0
  86. package/dist/env/index.mjs +5 -0
  87. package/dist/env/logger.d.mts +49 -0
  88. package/dist/env/logger.mjs +82 -0
  89. package/dist/env/logger.mjs.map +1 -0
  90. package/dist/error/codes.d.mts +199 -0
  91. package/dist/error/codes.mjs +57 -0
  92. package/dist/error/codes.mjs.map +1 -0
  93. package/dist/error/index.d.mts +20 -0
  94. package/dist/error/index.mjs +30 -0
  95. package/dist/error/index.mjs.map +1 -0
  96. package/dist/index.d.mts +8 -0
  97. package/dist/index.mjs +1 -0
  98. package/dist/oauth2/client-credentials-token.d.mts +37 -0
  99. package/dist/oauth2/client-credentials-token.mjs +55 -0
  100. package/dist/oauth2/client-credentials-token.mjs.map +1 -0
  101. package/dist/oauth2/create-authorization-url.d.mts +46 -0
  102. package/dist/oauth2/create-authorization-url.mjs +43 -0
  103. package/dist/oauth2/create-authorization-url.mjs.map +1 -0
  104. package/dist/oauth2/index.d.mts +8 -0
  105. package/dist/oauth2/index.mjs +8 -0
  106. package/dist/oauth2/oauth-provider.d.mts +195 -0
  107. package/dist/oauth2/refresh-access-token.d.mts +36 -0
  108. package/dist/oauth2/refresh-access-token.mjs +59 -0
  109. package/dist/oauth2/refresh-access-token.mjs.map +1 -0
  110. package/dist/oauth2/utils.d.mts +8 -0
  111. package/dist/oauth2/utils.mjs +28 -0
  112. package/dist/oauth2/utils.mjs.map +1 -0
  113. package/dist/oauth2/validate-authorization-code.d.mts +56 -0
  114. package/dist/oauth2/validate-authorization-code.mjs +72 -0
  115. package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
  116. package/dist/oauth2/verify.d.mts +43 -0
  117. package/dist/oauth2/verify.mjs +96 -0
  118. package/dist/oauth2/verify.mjs.map +1 -0
  119. package/dist/social-providers/apple.d.mts +120 -0
  120. package/dist/social-providers/apple.mjs +105 -0
  121. package/dist/social-providers/apple.mjs.map +1 -0
  122. package/dist/social-providers/atlassian.d.mts +73 -0
  123. package/dist/social-providers/atlassian.mjs +84 -0
  124. package/dist/social-providers/atlassian.mjs.map +1 -0
  125. package/dist/social-providers/cognito.d.mts +88 -0
  126. package/dist/social-providers/cognito.mjs +166 -0
  127. package/dist/social-providers/cognito.mjs.map +1 -0
  128. package/dist/social-providers/discord.d.mts +127 -0
  129. package/dist/social-providers/discord.mjs +65 -0
  130. package/dist/social-providers/discord.mjs.map +1 -0
  131. package/dist/social-providers/dropbox.d.mts +72 -0
  132. package/dist/social-providers/dropbox.mjs +76 -0
  133. package/dist/social-providers/dropbox.mjs.map +1 -0
  134. package/dist/social-providers/facebook.d.mts +82 -0
  135. package/dist/social-providers/facebook.mjs +121 -0
  136. package/dist/social-providers/facebook.mjs.map +1 -0
  137. package/dist/social-providers/figma.d.mts +64 -0
  138. package/dist/social-providers/figma.mjs +87 -0
  139. package/dist/social-providers/figma.mjs.map +1 -0
  140. package/dist/social-providers/github.d.mts +105 -0
  141. package/dist/social-providers/github.mjs +97 -0
  142. package/dist/social-providers/github.mjs.map +1 -0
  143. package/dist/social-providers/gitlab.d.mts +126 -0
  144. package/dist/social-providers/gitlab.mjs +83 -0
  145. package/dist/social-providers/gitlab.mjs.map +1 -0
  146. package/dist/social-providers/google.d.mts +100 -0
  147. package/dist/social-providers/google.mjs +109 -0
  148. package/dist/social-providers/google.mjs.map +1 -0
  149. package/dist/social-providers/huggingface.d.mts +86 -0
  150. package/dist/social-providers/huggingface.mjs +76 -0
  151. package/dist/social-providers/huggingface.mjs.map +1 -0
  152. package/dist/social-providers/index.d.mts +1725 -0
  153. package/dist/social-providers/index.mjs +77 -0
  154. package/dist/social-providers/index.mjs.map +1 -0
  155. package/dist/social-providers/kakao.d.mts +164 -0
  156. package/dist/social-providers/kakao.mjs +73 -0
  157. package/dist/social-providers/kakao.mjs.map +1 -0
  158. package/dist/social-providers/kick.d.mts +76 -0
  159. package/dist/social-providers/kick.mjs +72 -0
  160. package/dist/social-providers/kick.mjs.map +1 -0
  161. package/dist/social-providers/line.d.mts +108 -0
  162. package/dist/social-providers/line.mjs +114 -0
  163. package/dist/social-providers/line.mjs.map +1 -0
  164. package/dist/social-providers/linear.d.mts +71 -0
  165. package/dist/social-providers/linear.mjs +89 -0
  166. package/dist/social-providers/linear.mjs.map +1 -0
  167. package/dist/social-providers/linkedin.d.mts +70 -0
  168. package/dist/social-providers/linkedin.mjs +77 -0
  169. package/dist/social-providers/linkedin.mjs.map +1 -0
  170. package/dist/social-providers/microsoft-entra-id.d.mts +175 -0
  171. package/dist/social-providers/microsoft-entra-id.mjs +107 -0
  172. package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
  173. package/dist/social-providers/naver.d.mts +95 -0
  174. package/dist/social-providers/naver.mjs +68 -0
  175. package/dist/social-providers/naver.mjs.map +1 -0
  176. package/dist/social-providers/notion.d.mts +67 -0
  177. package/dist/social-providers/notion.mjs +76 -0
  178. package/dist/social-providers/notion.mjs.map +1 -0
  179. package/dist/social-providers/paybin.d.mts +74 -0
  180. package/dist/social-providers/paybin.mjs +86 -0
  181. package/dist/social-providers/paybin.mjs.map +1 -0
  182. package/dist/social-providers/paypal.d.mts +132 -0
  183. package/dist/social-providers/paypal.mjs +145 -0
  184. package/dist/social-providers/paypal.mjs.map +1 -0
  185. package/dist/social-providers/polar.d.mts +77 -0
  186. package/dist/social-providers/polar.mjs +74 -0
  187. package/dist/social-providers/polar.mjs.map +1 -0
  188. package/dist/social-providers/reddit.d.mts +65 -0
  189. package/dist/social-providers/reddit.mjs +84 -0
  190. package/dist/social-providers/reddit.mjs.map +1 -0
  191. package/dist/social-providers/roblox.d.mts +73 -0
  192. package/dist/social-providers/roblox.mjs +60 -0
  193. package/dist/social-providers/roblox.mjs.map +1 -0
  194. package/dist/social-providers/salesforce.d.mts +82 -0
  195. package/dist/social-providers/salesforce.mjs +92 -0
  196. package/dist/social-providers/salesforce.mjs.map +1 -0
  197. package/dist/social-providers/slack.d.mts +86 -0
  198. package/dist/social-providers/slack.mjs +69 -0
  199. package/dist/social-providers/slack.mjs.map +1 -0
  200. package/dist/social-providers/spotify.d.mts +66 -0
  201. package/dist/social-providers/spotify.mjs +72 -0
  202. package/dist/social-providers/spotify.mjs.map +1 -0
  203. package/dist/social-providers/tiktok.d.mts +171 -0
  204. package/dist/social-providers/tiktok.mjs +63 -0
  205. package/dist/social-providers/tiktok.mjs.map +1 -0
  206. package/dist/social-providers/twitch.d.mts +82 -0
  207. package/dist/social-providers/twitch.mjs +79 -0
  208. package/dist/social-providers/twitch.mjs.map +1 -0
  209. package/dist/social-providers/twitter.d.mts +129 -0
  210. package/dist/social-providers/twitter.mjs +88 -0
  211. package/dist/social-providers/twitter.mjs.map +1 -0
  212. package/dist/social-providers/vercel.d.mts +65 -0
  213. package/dist/social-providers/vercel.mjs +62 -0
  214. package/dist/social-providers/vercel.mjs.map +1 -0
  215. package/dist/social-providers/vk.d.mts +73 -0
  216. package/dist/social-providers/vk.mjs +84 -0
  217. package/dist/social-providers/vk.mjs.map +1 -0
  218. package/dist/social-providers/zoom.d.mts +173 -0
  219. package/dist/social-providers/zoom.mjs +73 -0
  220. package/dist/social-providers/zoom.mjs.map +1 -0
  221. package/dist/types/context.d.mts +267 -0
  222. package/dist/types/cookie.d.mts +16 -0
  223. package/dist/types/helper.d.mts +10 -0
  224. package/dist/types/index.d.mts +8 -0
  225. package/dist/types/init-options.d.mts +1314 -0
  226. package/dist/types/plugin-client.d.mts +112 -0
  227. package/dist/types/plugin.d.mts +125 -0
  228. package/dist/utils/db.d.mts +12 -0
  229. package/dist/utils/db.mjs +17 -0
  230. package/dist/utils/db.mjs.map +1 -0
  231. package/dist/utils/deprecate.d.mts +10 -0
  232. package/dist/utils/deprecate.mjs +18 -0
  233. package/dist/utils/deprecate.mjs.map +1 -0
  234. package/dist/utils/error-codes.d.mts +13 -0
  235. package/dist/utils/error-codes.mjs +12 -0
  236. package/dist/utils/error-codes.mjs.map +1 -0
  237. package/dist/utils/id.d.mts +5 -0
  238. package/dist/utils/id.mjs +10 -0
  239. package/dist/utils/id.mjs.map +1 -0
  240. package/dist/utils/ip.d.mts +55 -0
  241. package/dist/utils/ip.mjs +119 -0
  242. package/dist/utils/ip.mjs.map +1 -0
  243. package/dist/utils/json.d.mts +5 -0
  244. package/dist/utils/json.mjs +26 -0
  245. package/dist/utils/json.mjs.map +1 -0
  246. package/dist/utils/string.d.mts +5 -0
  247. package/dist/utils/string.mjs +8 -0
  248. package/dist/utils/string.mjs.map +1 -0
  249. package/dist/utils/url.d.mts +21 -0
  250. package/dist/utils/url.mjs +33 -0
  251. package/dist/utils/url.mjs.map +1 -0
  252. package/package.json +147 -0
  253. package/src/api/index.ts +106 -0
  254. package/src/async_hooks/index.ts +40 -0
  255. package/src/async_hooks/pure.index.ts +46 -0
  256. package/src/context/endpoint-context.ts +50 -0
  257. package/src/context/global.ts +57 -0
  258. package/src/context/index.ts +23 -0
  259. package/src/context/request-state.test.ts +94 -0
  260. package/src/context/request-state.ts +91 -0
  261. package/src/context/transaction.ts +136 -0
  262. package/src/db/adapter/factory.ts +1362 -0
  263. package/src/db/adapter/get-default-field-name.ts +59 -0
  264. package/src/db/adapter/get-default-model-name.ts +51 -0
  265. package/src/db/adapter/get-field-attributes.ts +62 -0
  266. package/src/db/adapter/get-field-name.ts +43 -0
  267. package/src/db/adapter/get-id-field.ts +141 -0
  268. package/src/db/adapter/get-model-name.ts +36 -0
  269. package/src/db/adapter/index.ts +554 -0
  270. package/src/db/adapter/types.ts +171 -0
  271. package/src/db/adapter/utils.ts +61 -0
  272. package/src/db/get-tables.ts +296 -0
  273. package/src/db/index.ts +18 -0
  274. package/src/db/plugin.ts +11 -0
  275. package/src/db/schema/account.ts +34 -0
  276. package/src/db/schema/rate-limit.ts +21 -0
  277. package/src/db/schema/session.ts +17 -0
  278. package/src/db/schema/shared.ts +7 -0
  279. package/src/db/schema/user.ts +16 -0
  280. package/src/db/schema/verification.ts +15 -0
  281. package/src/db/test/get-tables.test.ts +116 -0
  282. package/src/db/type.ts +180 -0
  283. package/src/env/color-depth.ts +172 -0
  284. package/src/env/env-impl.ts +124 -0
  285. package/src/env/index.ts +23 -0
  286. package/src/env/logger.test.ts +34 -0
  287. package/src/env/logger.ts +145 -0
  288. package/src/error/codes.ts +58 -0
  289. package/src/error/index.ts +35 -0
  290. package/src/index.ts +1 -0
  291. package/src/oauth2/client-credentials-token.ts +102 -0
  292. package/src/oauth2/create-authorization-url.ts +87 -0
  293. package/src/oauth2/index.ts +26 -0
  294. package/src/oauth2/oauth-provider.ts +222 -0
  295. package/src/oauth2/refresh-access-token.ts +124 -0
  296. package/src/oauth2/utils.ts +38 -0
  297. package/src/oauth2/validate-authorization-code.ts +149 -0
  298. package/src/oauth2/validate-token.test.ts +174 -0
  299. package/src/oauth2/verify.ts +221 -0
  300. package/src/social-providers/apple.ts +223 -0
  301. package/src/social-providers/atlassian.ts +132 -0
  302. package/src/social-providers/cognito.ts +279 -0
  303. package/src/social-providers/discord.ts +169 -0
  304. package/src/social-providers/dropbox.ts +112 -0
  305. package/src/social-providers/facebook.ts +206 -0
  306. package/src/social-providers/figma.ts +117 -0
  307. package/src/social-providers/github.ts +184 -0
  308. package/src/social-providers/gitlab.ts +155 -0
  309. package/src/social-providers/google.ts +199 -0
  310. package/src/social-providers/huggingface.ts +118 -0
  311. package/src/social-providers/index.ts +127 -0
  312. package/src/social-providers/kakao.ts +178 -0
  313. package/src/social-providers/kick.ts +109 -0
  314. package/src/social-providers/line.ts +169 -0
  315. package/src/social-providers/linear.ts +121 -0
  316. package/src/social-providers/linkedin.ts +110 -0
  317. package/src/social-providers/microsoft-entra-id.ts +259 -0
  318. package/src/social-providers/naver.ts +112 -0
  319. package/src/social-providers/notion.ts +108 -0
  320. package/src/social-providers/paybin.ts +122 -0
  321. package/src/social-providers/paypal.ts +263 -0
  322. package/src/social-providers/polar.ts +110 -0
  323. package/src/social-providers/reddit.ts +122 -0
  324. package/src/social-providers/roblox.ts +111 -0
  325. package/src/social-providers/salesforce.ts +159 -0
  326. package/src/social-providers/slack.ts +111 -0
  327. package/src/social-providers/spotify.ts +93 -0
  328. package/src/social-providers/tiktok.ts +209 -0
  329. package/src/social-providers/twitch.ts +111 -0
  330. package/src/social-providers/twitter.ts +198 -0
  331. package/src/social-providers/vercel.ts +87 -0
  332. package/src/social-providers/vk.ts +124 -0
  333. package/src/social-providers/zoom.ts +238 -0
  334. package/src/types/context.ts +396 -0
  335. package/src/types/cookie.ts +10 -0
  336. package/src/types/helper.ts +26 -0
  337. package/src/types/index.ts +32 -0
  338. package/src/types/init-options.ts +1529 -0
  339. package/src/types/plugin-client.ts +127 -0
  340. package/src/types/plugin.ts +157 -0
  341. package/src/utils/db.ts +20 -0
  342. package/src/utils/deprecate.test.ts +72 -0
  343. package/src/utils/deprecate.ts +21 -0
  344. package/src/utils/error-codes.ts +65 -0
  345. package/src/utils/id.ts +5 -0
  346. package/src/utils/ip.test.ts +255 -0
  347. package/src/utils/ip.ts +211 -0
  348. package/src/utils/json.ts +25 -0
  349. package/src/utils/string.ts +3 -0
  350. package/src/utils/url.ts +43 -0
  351. package/tsconfig.json +7 -0
  352. package/tsdown.config.ts +35 -0
  353. package/vitest.config.ts +3 -0
@@ -0,0 +1,1529 @@
1
+ import type { Database as BunDatabase } from "bun:sqlite";
2
+ import type { DatabaseSync } from "node:sqlite";
3
+ import type { CookieOptions } from "better-call";
4
+ import type {
5
+ Dialect,
6
+ Kysely,
7
+ MysqlPool,
8
+ PostgresPool,
9
+ SqliteDatabase,
10
+ } from "kysely";
11
+ import type { AuthMiddleware } from "../api";
12
+ import type {
13
+ Account,
14
+ DBFieldAttribute,
15
+ ModelNames,
16
+ RateLimit,
17
+ SecondaryStorage,
18
+ Session,
19
+ User,
20
+ Verification,
21
+ } from "../db";
22
+ import type { DBAdapterDebugLogOption, DBAdapterInstance } from "../db/adapter";
23
+ import type { Logger } from "../env";
24
+ import type { SocialProviderList, SocialProviders } from "../social-providers";
25
+ import type { AuthContext, GenericEndpointContext } from "./context";
26
+ import type { Awaitable, LiteralUnion } from "./helper";
27
+ import type { BetterAuthPlugin } from "./plugin";
28
+
29
+ type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql";
30
+ type OmitId<T extends { id: unknown }> = Omit<T, "id">;
31
+ type Optional<T> = {
32
+ [P in keyof T]?: T[P] | undefined;
33
+ };
34
+
35
+ export type StoreIdentifierOption =
36
+ | "plain"
37
+ | "hashed"
38
+ | { hash: (identifier: string) => Promise<string> };
39
+
40
+ export type GenerateIdFn = (options: {
41
+ model: ModelNames;
42
+ size?: number | undefined;
43
+ }) => string | false;
44
+
45
+ export interface BetterAuthRateLimitStorage {
46
+ get: (key: string) => Promise<RateLimit | null | undefined>;
47
+ set: (
48
+ key: string,
49
+ value: RateLimit,
50
+ update?: boolean | undefined,
51
+ ) => Promise<void>;
52
+ }
53
+
54
+ export type BetterAuthRateLimitRule = {
55
+ /**
56
+ * Default window to use for rate limiting. The value
57
+ * should be in seconds.
58
+ *
59
+ * @default 10 seconds
60
+ */
61
+ window: number;
62
+ /**
63
+ * The default maximum number of requests allowed within the window.
64
+ *
65
+ * @default 100 requests
66
+ */
67
+ max: number;
68
+ };
69
+
70
+ export type BetterAuthRateLimitOptions = Optional<BetterAuthRateLimitRule> & {
71
+ /**
72
+ * By default, rate limiting is only
73
+ * enabled on production.
74
+ */
75
+ enabled?: boolean | undefined;
76
+ /**
77
+ * Custom rate limit rules to apply to
78
+ * specific paths.
79
+ */
80
+ customRules?:
81
+ | {
82
+ [key: string]:
83
+ | BetterAuthRateLimitRule
84
+ | false
85
+ | ((
86
+ request: Request,
87
+ currentRule: BetterAuthRateLimitRule,
88
+ ) => Awaitable<false | BetterAuthRateLimitRule>);
89
+ }
90
+ | undefined;
91
+ /**
92
+ * Storage configuration
93
+ *
94
+ * By default, rate limiting is stored in memory. If you passed a
95
+ * secondary storage, rate limiting will be stored in the secondary
96
+ * storage.
97
+ *
98
+ * @default "memory"
99
+ */
100
+ storage?: ("memory" | "database" | "secondary-storage") | undefined;
101
+ /**
102
+ * If database is used as storage, the name of the table to
103
+ * use for rate limiting.
104
+ *
105
+ * @default "rateLimit"
106
+ */
107
+ modelName?: string | undefined;
108
+ /**
109
+ * Custom field names for the rate limit table
110
+ */
111
+ fields?: Partial<Record<keyof RateLimit, string>> | undefined;
112
+ /**
113
+ * custom storage configuration.
114
+ *
115
+ * NOTE: If custom storage is used storage
116
+ * is ignored
117
+ */
118
+ customStorage?: BetterAuthRateLimitStorage;
119
+ };
120
+
121
+ export type BetterAuthAdvancedOptions = {
122
+ /**
123
+ * Ip address configuration
124
+ */
125
+ ipAddress?:
126
+ | {
127
+ /**
128
+ * List of headers to use for ip address
129
+ *
130
+ * Ip address is used for rate limiting and session tracking
131
+ *
132
+ * @example ["x-client-ip", "x-forwarded-for", "cf-connecting-ip"]
133
+ *
134
+ * @default
135
+ * @link https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/utils/get-request-ip.ts#L8
136
+ */
137
+ ipAddressHeaders?: string[];
138
+ /**
139
+ * Disable ip tracking
140
+ *
141
+ * ⚠︎ This is a security risk and it may expose your application to abuse
142
+ */
143
+ disableIpTracking?: boolean;
144
+ /**
145
+ * IPv6 subnet prefix length for rate limiting.
146
+ * IPv6 addresses will be normalized to this subnet.
147
+ *
148
+ * @default 64
149
+ */
150
+ ipv6Subnet?: 128 | 64 | 48 | 32;
151
+ }
152
+ | undefined;
153
+ /**
154
+ * Use secure cookies
155
+ *
156
+ * @default false
157
+ */
158
+ useSecureCookies?: boolean | undefined;
159
+ /**
160
+ * Disable all CSRF protection.
161
+ *
162
+ * When enabled, this disables:
163
+ * - Origin header validation when cookies are present
164
+ * - Fetch Metadata checks (Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest)
165
+ * - Cross-site navigation blocking for first-login scenarios
166
+ *
167
+ * ⚠︎ This is a security risk and it may expose your application to
168
+ * CSRF attacks
169
+ *
170
+ * @default false
171
+ */
172
+ disableCSRFCheck?: boolean | undefined;
173
+ /**
174
+ * Disable URL validation against trustedOrigins.
175
+ *
176
+ * When enabled, this disables validation of:
177
+ * - callbackURL
178
+ * - redirectTo
179
+ * - errorCallbackURL
180
+ * - newUserCallbackURL
181
+ *
182
+ * ⚠︎ This may allow open redirects and could lead to security
183
+ * vulnerabilities.
184
+ *
185
+ * @default false
186
+ */
187
+ disableOriginCheck?: boolean | undefined;
188
+ /**
189
+ * Configure cookies to be cross subdomains
190
+ */
191
+ crossSubDomainCookies?:
192
+ | {
193
+ /**
194
+ * Enable cross subdomain cookies
195
+ */
196
+ enabled: boolean;
197
+ /**
198
+ * Additional cookies to be shared across subdomains
199
+ */
200
+ additionalCookies?: string[];
201
+ /**
202
+ * The domain to use for the cookies
203
+ *
204
+ * By default, the domain will be the root
205
+ * domain from the base URL.
206
+ */
207
+ domain?: string;
208
+ }
209
+ | undefined;
210
+ /*
211
+ * Allows you to change default cookie names and attributes
212
+ *
213
+ * default cookie names:
214
+ * - "session_token"
215
+ * - "session_data"
216
+ * - "dont_remember"
217
+ * - "account_data"
218
+ *
219
+ * plugins can also add additional cookies
220
+ */
221
+ cookies?:
222
+ | {
223
+ [key: string]: {
224
+ name?: string;
225
+ attributes?: CookieOptions;
226
+ };
227
+ }
228
+ | undefined;
229
+ defaultCookieAttributes?: CookieOptions | undefined;
230
+ /**
231
+ * Prefix for cookies. If a cookie name is provided
232
+ * in cookies config, this will be overridden.
233
+ *
234
+ * @default
235
+ * ```txt
236
+ * "appName" -> which defaults to "better-auth"
237
+ * ```
238
+ */
239
+ cookiePrefix?: string | undefined;
240
+ /**
241
+ * Database configuration.
242
+ */
243
+ database?:
244
+ | {
245
+ /**
246
+ * The default number of records to return from the database
247
+ * when using the `findMany` adapter method.
248
+ *
249
+ * @default 100
250
+ */
251
+ defaultFindManyLimit?: number;
252
+ /**
253
+ * If your database auto increments number ids, set this to `true`.
254
+ *
255
+ * Note: If enabled, we will not handle ID generation (including if you use `generateId`), and it would be expected that your database will provide the ID automatically.
256
+ *
257
+ * @default false
258
+ *
259
+ * @deprecated Please use `generateId` instead. This will be removed in future
260
+ * releases.
261
+ */
262
+ useNumberId?: boolean;
263
+ /**
264
+ * Custom generateId function.
265
+ *
266
+ * If not provided, random ids will be generated.
267
+ * If set to false, the database's auto generated id
268
+ * will be used.
269
+ *
270
+ * If set to "serial", the database's auto generated
271
+ * id will be used.
272
+ *
273
+ * If set to "uuid", we generate a random UUID for
274
+ * the id. If postgres, we use the `gen_random_uuid()
275
+ * ` function. If mysql or mssql, we use the `uuid()`
276
+ * function.
277
+ */
278
+ generateId?: GenerateIdFn | false | "serial" | "uuid";
279
+ }
280
+ | undefined;
281
+ /**
282
+ * Trusted proxy headers
283
+ *
284
+
285
+ * - `x-forwarded-host`
286
+ * - `x-forwarded-proto`
287
+ *
288
+ * If set to `true` and no `baseURL` option is provided, we will use the headers to infer the
289
+ * base URL.
290
+ *
291
+ * ⚠︎ This may expose your application to security vulnerabilities if not
292
+ * used correctly. Please use this with caution.
293
+ */
294
+ trustedProxyHeaders?: boolean | undefined;
295
+ /**
296
+ * Configure background task handling for deferred operations.
297
+ *
298
+ * Background tasks allow non-critical operations (like cleanup, analytics,
299
+ * or timing-attack mitigation) to run after the response is sent.
300
+ *
301
+ * Use `waitUntil` from `@vercel/functions` on Vercel,
302
+ * or `ctx.waitUntil` on Cloudflare Workers.
303
+ *
304
+ * @example
305
+ * // Vercel
306
+ * import { waitUntil } from "@vercel/functions";
307
+ * advanced: { backgroundTasks: { handler: waitUntil } }
308
+ *
309
+ * @example
310
+ * // Cloudflare Workers (with AsyncLocalStorage)
311
+ * advanced: {
312
+ * backgroundTasks: {
313
+ * handler: (p) => execCtxStorage.getStore()?.waitUntil(p)
314
+ * }
315
+ * }
316
+ */
317
+ backgroundTasks?: {
318
+ handler: (promise: Promise<unknown>) => void;
319
+ };
320
+ /**
321
+ * Skip trailing slashes in API routes.
322
+ *
323
+ * When enabled, requests with trailing slashes (e.g., `/api/auth/session/`)
324
+ * will be handled the same as requests without (e.g., `/api/auth/session`).
325
+ *
326
+ * @default false
327
+ */
328
+ skipTrailingSlashes?: boolean;
329
+ };
330
+
331
+ export type BetterAuthOptions = {
332
+ /**
333
+ * The name of the application
334
+ *
335
+ * process.env.APP_NAME
336
+ *
337
+ * @default "Better Auth"
338
+ */
339
+ appName?: string | undefined;
340
+ /**
341
+ * Base URL for the Better Auth. This is typically the
342
+ * root URL where your application server is hosted.
343
+ * If not explicitly set,
344
+ * the system will check the following environment variable:
345
+ *
346
+ * process.env.BETTER_AUTH_URL
347
+ */
348
+ baseURL?: string | undefined;
349
+ /**
350
+ * Base path for the Better Auth. This is typically
351
+ * the path where the
352
+ * Better Auth routes are mounted.
353
+ *
354
+ * @default "/api/auth"
355
+ */
356
+ basePath?: string | undefined;
357
+ /**
358
+ * The secret to use for encryption,
359
+ * signing and hashing.
360
+ *
361
+ * By default Better Auth will look for
362
+ * the following environment variables:
363
+ * process.env.BETTER_AUTH_SECRET,
364
+ * process.env.AUTH_SECRET
365
+ * If none of these environment
366
+ * variables are set,
367
+ * it will default to
368
+ * "better-auth-secret-123456789".
369
+ *
370
+ * on production if it's not set
371
+ * it will throw an error.
372
+ *
373
+ * you can generate a good secret
374
+ * using the following command:
375
+ * @example
376
+ * ```bash
377
+ * openssl rand -base64 32
378
+ * ```
379
+ */
380
+ secret?: string | undefined;
381
+ /**
382
+ * Database configuration
383
+ */
384
+ database?:
385
+ | (
386
+ | PostgresPool
387
+ | MysqlPool
388
+ | SqliteDatabase
389
+ | Dialect
390
+ | DBAdapterInstance
391
+ | BunDatabase
392
+ | DatabaseSync
393
+ | {
394
+ dialect: Dialect;
395
+ type: KyselyDatabaseType;
396
+ /**
397
+ * casing for table names
398
+ *
399
+ * @default "camel"
400
+ */
401
+ casing?: "snake" | "camel";
402
+ /**
403
+ * Enable debug logs for the adapter
404
+ *
405
+ * @default false
406
+ */
407
+ debugLogs?: DBAdapterDebugLogOption;
408
+ /**
409
+ * Whether to execute multiple operations in a transaction.
410
+ * If the database doesn't support transactions,
411
+ * set this to `false` and operations will be executed sequentially.
412
+ *
413
+ * @default false
414
+ */
415
+ transaction?: boolean;
416
+ }
417
+ | {
418
+ /**
419
+ * Kysely instance
420
+ */
421
+ db: Kysely<any>;
422
+ /**
423
+ * Database type between postgres, mysql and sqlite
424
+ */
425
+ type: KyselyDatabaseType;
426
+ /**
427
+ * casing for table names
428
+ *
429
+ * @default "camel"
430
+ */
431
+ casing?: "snake" | "camel";
432
+ /**
433
+ * Enable debug logs for the adapter
434
+ *
435
+ * @default false
436
+ */
437
+ debugLogs?: DBAdapterDebugLogOption;
438
+ /**
439
+ * Whether to execute multiple operations in a transaction.
440
+ * If the database doesn't support transactions,
441
+ * set this to `false` and operations will be executed sequentially.
442
+ *
443
+ * @default false
444
+ */
445
+ transaction?: boolean;
446
+ }
447
+ )
448
+ | undefined;
449
+ /**
450
+ * Secondary storage configuration
451
+ *
452
+ * This is used to store session and rate limit data.
453
+ */
454
+ secondaryStorage?: SecondaryStorage | undefined;
455
+ /**
456
+ * Email verification configuration
457
+ */
458
+ emailVerification?:
459
+ | {
460
+ /**
461
+ * Send a verification email
462
+ * @param data the data object
463
+ * @param request the request object
464
+ */
465
+ sendVerificationEmail?: (
466
+ /**
467
+ * @param user the user to send the
468
+ * verification email to
469
+ * @param url the URL to send the verification email to
470
+ * it contains the token as well
471
+ * @param token the token to send the verification email to
472
+ */
473
+ data: {
474
+ user: User;
475
+ url: string;
476
+ token: string;
477
+ },
478
+ /**
479
+ * The request object
480
+ */
481
+ request?: Request,
482
+ ) => Promise<void>;
483
+ /**
484
+ * Send a verification email automatically after sign up.
485
+ *
486
+ * - `true`: Always send verification email on sign up
487
+ * - `false`: Never send verification email on sign up
488
+ * - `undefined`: Follows `requireEmailVerification` behavior
489
+ *
490
+ * @default undefined
491
+ */
492
+ sendOnSignUp?: boolean;
493
+ /**
494
+ * Send a verification email automatically
495
+ * on sign in when the user's email is not verified
496
+ *
497
+ * @default false
498
+ */
499
+ sendOnSignIn?: boolean;
500
+ /**
501
+ * Auto signin the user after they verify their email
502
+ */
503
+ autoSignInAfterVerification?: boolean;
504
+ /**
505
+ * Number of seconds the verification token is
506
+ * valid for.
507
+ * @default 3600 seconds (1 hour)
508
+ */
509
+ expiresIn?: number;
510
+ /**
511
+ * A function that is called when a user verifies their email
512
+ * @param user the user that verified their email
513
+ * @param request the request object
514
+ * @deprecated Use `beforeEmailVerification` or `afterEmailVerification` instead. This will be removed in 1.5
515
+ */
516
+ onEmailVerification?: (user: User, request?: Request) => Promise<void>;
517
+ /**
518
+ * A function that is called before a user verifies their email
519
+ * @param user the user that verified their email
520
+ * @param request the request object
521
+ */
522
+ beforeEmailVerification?: (
523
+ user: User,
524
+ request?: Request,
525
+ ) => Promise<void>;
526
+ /**
527
+ * A function that is called when a user's email is updated to verified
528
+ * @param user the user that verified their email
529
+ * @param request the request object
530
+ */
531
+ afterEmailVerification?: (
532
+ user: User,
533
+ request?: Request,
534
+ ) => Promise<void>;
535
+ }
536
+ | undefined;
537
+ /**
538
+ * Email and password authentication
539
+ */
540
+ emailAndPassword?:
541
+ | {
542
+ /**
543
+ * Enable email and password authentication
544
+ *
545
+ * @default false
546
+ */
547
+ enabled: boolean;
548
+ /**
549
+ * Disable email and password sign up
550
+ *
551
+ * @default false
552
+ */
553
+ disableSignUp?: boolean;
554
+ /**
555
+ * Require email verification before a session
556
+ * can be created for the user.
557
+ *
558
+ * if the user is not verified, the user will not be able to sign in
559
+ * and on sign in attempts, the user will be prompted to verify their email.
560
+ */
561
+ requireEmailVerification?: boolean;
562
+ /**
563
+ * The maximum length of the password.
564
+ *
565
+ * @default 128
566
+ */
567
+ maxPasswordLength?: number;
568
+ /**
569
+ * The minimum length of the password.
570
+ *
571
+ * @default 8
572
+ */
573
+ minPasswordLength?: number;
574
+ /**
575
+ * send reset password
576
+ */
577
+ sendResetPassword?: (
578
+ /**
579
+ * @param user the user to send the
580
+ * reset password email to
581
+ * @param url the URL to send the reset password email to
582
+ * @param token the token to send to the user (could be used instead of sending the url
583
+ * if you need to redirect the user to custom route)
584
+ */
585
+ data: { user: User; url: string; token: string },
586
+ /**
587
+ * The request object
588
+ */
589
+ request?: Request,
590
+ ) => Promise<void>;
591
+ /**
592
+ * Number of seconds the reset password token is
593
+ * valid for.
594
+ * @default 1 hour (60 * 60)
595
+ */
596
+ resetPasswordTokenExpiresIn?: number;
597
+ /**
598
+ * A callback function that is triggered
599
+ * when a user's password is changed successfully.
600
+ */
601
+ onPasswordReset?: (
602
+ data: { user: User },
603
+ request?: Request,
604
+ ) => Promise<void>;
605
+ /**
606
+ * Password hashing and verification
607
+ *
608
+ * By default Scrypt is used for password hashing and
609
+ * verification. You can provide your own hashing and
610
+ * verification function. if you want to use a
611
+ * different algorithm.
612
+ */
613
+ password?: {
614
+ hash?: (password: string) => Promise<string>;
615
+ verify?: (data: {
616
+ hash: string;
617
+ password: string;
618
+ }) => Promise<boolean>;
619
+ };
620
+ /**
621
+ * Automatically sign in the user after sign up
622
+ *
623
+ * @default true
624
+ */
625
+ autoSignIn?: boolean;
626
+ /**
627
+ * Whether to revoke all other sessions when resetting password
628
+ * @default false
629
+ */
630
+ revokeSessionsOnPasswordReset?: boolean;
631
+ }
632
+ | undefined;
633
+ /**
634
+ * list of social providers
635
+ */
636
+ socialProviders?: SocialProviders | undefined;
637
+ /**
638
+ * List of Better Auth plugins
639
+ */
640
+ plugins?: ([] | BetterAuthPlugin[]) | undefined;
641
+ /**
642
+ * User configuration
643
+ */
644
+ user?:
645
+ | {
646
+ /**
647
+ * The model name for the user. Defaults to "user".
648
+ */
649
+ modelName?: string;
650
+ /**
651
+ * Map fields
652
+ *
653
+ * @example
654
+ * ```ts
655
+ * {
656
+ * userId: "user_id"
657
+ * }
658
+ * ```
659
+ */
660
+ fields?: Partial<Record<keyof OmitId<User>, string>>;
661
+ /**
662
+ * Additional fields for the user
663
+ */
664
+ additionalFields?: {
665
+ [key: string]: DBFieldAttribute;
666
+ };
667
+ /**
668
+ * Changing email configuration
669
+ */
670
+ changeEmail?: {
671
+ /**
672
+ * Enable changing email
673
+ * @default false
674
+ */
675
+ enabled: boolean;
676
+ /**
677
+ * Send a verification email when the user changes their email.
678
+ * @param data the data object
679
+ * @param request the request object
680
+ * @deprecated Use `sendChangeEmailConfirmation` instead
681
+ */
682
+ sendChangeEmailVerification?: (
683
+ data: {
684
+ user: User;
685
+ newEmail: string;
686
+ url: string;
687
+ token: string;
688
+ },
689
+ request?: Request,
690
+ ) => Promise<void>;
691
+ /**
692
+ * Send a confirmation email to the old email address when the user changes their email.
693
+ * @param data the data object
694
+ * @param request the request object
695
+ */
696
+ sendChangeEmailConfirmation?: (
697
+ data: {
698
+ user: User;
699
+ newEmail: string;
700
+ url: string;
701
+ token: string;
702
+ },
703
+ request?: Request,
704
+ ) => Promise<void>;
705
+ /**
706
+ * Update the email without verification if the user is not verified.
707
+ * @default false
708
+ */
709
+ updateEmailWithoutVerification?: boolean;
710
+ };
711
+ /**
712
+ * User deletion configuration
713
+ */
714
+ deleteUser?: {
715
+ /**
716
+ * Enable user deletion
717
+ */
718
+ enabled?: boolean;
719
+ /**
720
+ * Send a verification email when the user deletes their account.
721
+ *
722
+ * if this is not set, the user will be deleted immediately.
723
+ * @param data the data object
724
+ * @param request the request object
725
+ */
726
+ sendDeleteAccountVerification?: (
727
+ data: {
728
+ user: User;
729
+ url: string;
730
+ token: string;
731
+ },
732
+ request?: Request,
733
+ ) => Promise<void>;
734
+ /**
735
+ * A function that is called before a user is deleted.
736
+ *
737
+ * to interrupt with error you can throw `APIError`
738
+ */
739
+ beforeDelete?: (user: User, request?: Request) => Promise<void>;
740
+ /**
741
+ * A function that is called after a user is deleted.
742
+ *
743
+ * This is useful for cleaning up user data
744
+ */
745
+ afterDelete?: (user: User, request?: Request) => Promise<void>;
746
+ /**
747
+ * The expiration time for the delete token.
748
+ *
749
+ * @default 1 day (60 * 60 * 24) in seconds
750
+ */
751
+ deleteTokenExpiresIn?: number;
752
+ };
753
+ }
754
+ | undefined;
755
+ session?:
756
+ | {
757
+ /**
758
+ * The model name for the session.
759
+ *
760
+ * @default "session"
761
+ */
762
+ modelName?: string;
763
+ /**
764
+ * Map fields
765
+ *
766
+ * @example
767
+ * ```ts
768
+ * {
769
+ * userId: "user_id"
770
+ * }
771
+ */
772
+ fields?: Partial<Record<keyof OmitId<Session>, string>>;
773
+ /**
774
+ * Expiration time for the session token. The value
775
+ * should be in seconds.
776
+ * @default 7 days (60 * 60 * 24 * 7)
777
+ */
778
+ expiresIn?: number;
779
+ /**
780
+ * How often the session should be refreshed. The value
781
+ * should be in seconds.
782
+ * If set 0 the session will be refreshed every time it is used.
783
+ * @default 1 day (60 * 60 * 24)
784
+ */
785
+ updateAge?: number;
786
+ /**
787
+ * Disable session refresh so that the session is not updated
788
+ * regardless of the `updateAge` option.
789
+ *
790
+ * @default false
791
+ */
792
+ disableSessionRefresh?: boolean;
793
+ /**
794
+ * Defer session refresh writes to POST requests.
795
+ * When enabled, GET is read-only and POST performs refresh.
796
+ * Useful for read-replica database setups.
797
+ *
798
+ * @default false
799
+ */
800
+ deferSessionRefresh?: boolean;
801
+ /**
802
+ * Additional fields for the session
803
+ */
804
+ additionalFields?: {
805
+ [key: string]: DBFieldAttribute;
806
+ };
807
+ /**
808
+ * By default if secondary storage is provided
809
+ * the session is stored in the secondary storage.
810
+ *
811
+ * Set this to true to store the session in the database
812
+ * as well.
813
+ *
814
+ * Reads are always done from the secondary storage.
815
+ *
816
+ * @default false
817
+ */
818
+ storeSessionInDatabase?: boolean;
819
+ /**
820
+ * By default, sessions are deleted from the database when secondary storage
821
+ * is provided when session is revoked.
822
+ *
823
+ * Set this to true to preserve session records in the database,
824
+ * even if they are deleted from the secondary storage.
825
+ *
826
+ * @default false
827
+ */
828
+ preserveSessionInDatabase?: boolean;
829
+ /**
830
+ * Enable caching session in cookie
831
+ */
832
+ cookieCache?: {
833
+ /**
834
+ * max age of the cookie
835
+ * @default 5 minutes (5 * 60)
836
+ */
837
+ maxAge?: number;
838
+ /**
839
+ * Enable caching session in cookie
840
+ * @default false
841
+ */
842
+ enabled?: boolean;
843
+ /**
844
+ * Strategy for encoding/decoding cookie cache
845
+ *
846
+ * - "compact": Uses base64url encoding with HMAC-SHA256 signature (compact format, no JWT spec overhead)
847
+ * - "jwt": Uses JWT with HMAC signature (no encryption, follows JWT spec)
848
+ * - "jwe": Uses JWE (JSON Web Encryption) with A256CBC-HS512 and HKDF key derivation for secure encrypted tokens
849
+ *
850
+ * @default "compact"
851
+ */
852
+ strategy?: "compact" | "jwt" | "jwe";
853
+ /**
854
+ * Controls stateless cookie cache refresh behavior.
855
+ *
856
+ * When enabled, the cookie cache will be automatically refreshed before expiry
857
+ * WITHOUT querying the database. This is essential for fully stateless or DB-less scenarios.
858
+ *
859
+ * - `false`: Disable automatic refresh. Cache is only invalidated when it reaches maxAge expiry.
860
+ * - `true`: Enable automatic refresh with default settings (refreshes when 80% of maxAge is reached).
861
+ * - `object`: Custom refresh configuration with either `updateAge` or `shouldRefresh` function
862
+ *
863
+ * Note: When the cache expires (reaches maxAge), it will attempt to fetch from database if available.
864
+ * The refreshCache option is specifically for refreshing BEFORE expiry in a stateless manner.
865
+ *
866
+ * @default false
867
+ */
868
+ refreshCache?:
869
+ | boolean
870
+ | {
871
+ /**
872
+ * Time in seconds before expiry when the cache should be refreshed.
873
+ * For example, if maxAge is 300 (5 minutes) and updateAge is 60,
874
+ * the cache will be refreshed when it has 60 seconds left before expiry.
875
+ *
876
+ * @default 20% of maxAge
877
+ */
878
+ updateAge?: number;
879
+ };
880
+ /**
881
+ * Version of the cookie cache
882
+ *
883
+ * If a cookie cache version is changed, all existing cookie caches with the old version
884
+ * will be invalidated.
885
+ *
886
+ * It can be a string or a function that returns a string or a promise that returns a string.
887
+ * If it's a function, it will be called with the session and user data
888
+ *
889
+ * @default "1"
890
+ */
891
+ version?:
892
+ | string
893
+ | ((
894
+ session: Session & Record<string, any>,
895
+ user: User & Record<string, any>,
896
+ ) => string)
897
+ | ((
898
+ session: Session & Record<string, any>,
899
+ user: User & Record<string, any>,
900
+ ) => Promise<string>);
901
+ };
902
+ /**
903
+ * The age of the session to consider it fresh.
904
+ *
905
+ * This is used to check if the session is fresh
906
+ * for sensitive operations. (e.g. deleting an account)
907
+ *
908
+ * If the session is not fresh, the user should be prompted
909
+ * to sign in again.
910
+ *
911
+ * If set to 0, the session will be considered fresh every time. (⚠︎ not recommended)
912
+ *
913
+ * @default 1 day (60 * 60 * 24)
914
+ */
915
+ freshAge?: number;
916
+ }
917
+ | undefined;
918
+ account?:
919
+ | {
920
+ /**
921
+ * The model name for the account. Defaults to "account".
922
+ */
923
+ modelName?: string;
924
+ /**
925
+ * Map fields
926
+ */
927
+ fields?: Partial<Record<keyof OmitId<Account>, string>>;
928
+ /**
929
+ * Additional fields for the account
930
+ */
931
+ additionalFields?: {
932
+ [key: string]: DBFieldAttribute;
933
+ };
934
+ /**
935
+ * When enabled (true), the user account data (accessToken, idToken, refreshToken, etc.)
936
+ * will be updated on sign in with the latest data from the provider.
937
+ *
938
+ * @default true
939
+ */
940
+ updateAccountOnSignIn?: boolean;
941
+ /**
942
+ * Configuration for account linking.
943
+ */
944
+ accountLinking?: {
945
+ /**
946
+ * Enable account linking
947
+ *
948
+ * @default true
949
+ */
950
+ enabled?: boolean;
951
+ /**
952
+ * Disable implicit account linking on sign-in.
953
+ *
954
+ * When enabled, accounts will not be automatically linked
955
+ * during OAuth sign-in, even if the email is verified or
956
+ * the provider is trusted. Users must explicitly link
957
+ * accounts using `linkSocial()` while authenticated.
958
+ *
959
+ * @default false
960
+ */
961
+ disableImplicitLinking?: boolean;
962
+ /**
963
+ * List of trusted providers
964
+ */
965
+ trustedProviders?: Array<
966
+ LiteralUnion<SocialProviderList[number] | "email-password", string>
967
+ >;
968
+ /**
969
+ * If enabled (true), this will allow users to manually linking accounts with different email addresses than the main user.
970
+ *
971
+ * @default false
972
+ *
973
+ * ⚠️ Warning: enabling this might lead to account takeovers, so proceed with caution.
974
+ */
975
+ allowDifferentEmails?: boolean;
976
+ /**
977
+ * If enabled (true), this will allow users to unlink all accounts.
978
+ *
979
+ * @default false
980
+ */
981
+ allowUnlinkingAll?: boolean;
982
+ /**
983
+ * If enabled (true), this will update the user information based on the newly linked account
984
+ *
985
+ * @default false
986
+ */
987
+ updateUserInfoOnLink?: boolean;
988
+ };
989
+ /**
990
+ * Encrypt OAuth tokens
991
+ *
992
+ * By default, OAuth tokens (access tokens, refresh tokens, ID tokens) are stored in plain text in the database.
993
+ * This poses a security risk if your database is compromised, as attackers could gain access to user accounts
994
+ * on external services.
995
+ *
996
+ * When enabled, tokens are encrypted using AES-256-GCM before storage, providing protection against:
997
+ * - Database breaches and unauthorized access to raw token data
998
+ * - Internal threats from database administrators or compromised credentials
999
+ * - Token exposure in database backups and logs
1000
+ * @default false
1001
+ */
1002
+ encryptOAuthTokens?: boolean;
1003
+ /**
1004
+ * Skip state cookie check
1005
+ *
1006
+ * ⚠︎ this has security implications and should only be enabled if you know what you are doing.
1007
+ * @default false
1008
+ */
1009
+ skipStateCookieCheck?: boolean;
1010
+ /**
1011
+ * Strategy for storing OAuth state
1012
+ *
1013
+ * - "cookie": Store state in an encrypted cookie (stateless)
1014
+ * - "database": Store state in the database
1015
+ *
1016
+ * @default "cookie"
1017
+ */
1018
+ storeStateStrategy?: "database" | "cookie";
1019
+ /**
1020
+ * Store account data after oauth flow on a cookie
1021
+ *
1022
+ * This is useful for database-less flow
1023
+ *
1024
+ * @default false
1025
+ *
1026
+ * @note This is automatically set to true if you haven't passed a database
1027
+ */
1028
+ storeAccountCookie?: boolean;
1029
+ }
1030
+ | undefined;
1031
+ /**
1032
+ * Verification configuration
1033
+ */
1034
+ verification?:
1035
+ | {
1036
+ /**
1037
+ * Change the modelName of the verification table
1038
+ */
1039
+ modelName?: string;
1040
+ /**
1041
+ * Map verification fields
1042
+ */
1043
+ fields?: Partial<Record<keyof OmitId<Verification>, string>>;
1044
+ /**
1045
+ * Additional fields for the verification
1046
+ */
1047
+ additionalFields?: {
1048
+ [key: string]: DBFieldAttribute;
1049
+ };
1050
+ /**
1051
+ * disable cleaning up expired values when a verification value is
1052
+ * fetched
1053
+ */
1054
+ disableCleanup?: boolean;
1055
+ /**
1056
+ * How to store verification identifiers (tokens, OTPs, etc.)
1057
+ *
1058
+ * @example "hashed"
1059
+ *
1060
+ * @default "plain"
1061
+ */
1062
+ storeIdentifier?:
1063
+ | StoreIdentifierOption
1064
+ | {
1065
+ default: StoreIdentifierOption;
1066
+ overrides?: Record<string, StoreIdentifierOption>;
1067
+ };
1068
+ /**
1069
+ * Store verification data in database even when secondary storage is configured.
1070
+ * @default false
1071
+ */
1072
+ storeInDatabase?: boolean;
1073
+ }
1074
+ | undefined;
1075
+ /**
1076
+ * List of trusted origins.
1077
+ *
1078
+ * @param request - The request object.
1079
+ * It'll be undefined if no request was
1080
+ * made. Like during a create context call
1081
+ * or `auth.api` call.
1082
+ *
1083
+ * Trusted origins will be dynamically
1084
+ * calculated based on the request.
1085
+ *
1086
+ * @example
1087
+ * ```ts
1088
+ * trustedOrigins: async (request) => {
1089
+ * return [
1090
+ * "https://better-auth.com",
1091
+ * "https://*.better-auth.com",
1092
+ * request.headers.get("x-custom-origin")
1093
+ * ];
1094
+ * }
1095
+ * ```
1096
+ * @returns An array of trusted origins.
1097
+ */
1098
+ trustedOrigins?:
1099
+ | (
1100
+ | string[]
1101
+ | ((
1102
+ request?: Request | undefined,
1103
+ ) => Awaitable<(string | undefined | null)[]>)
1104
+ )
1105
+ | undefined;
1106
+ /**
1107
+ * Rate limiting configuration
1108
+ */
1109
+ rateLimit?: BetterAuthRateLimitOptions | undefined;
1110
+ /**
1111
+ * Advanced options
1112
+ */
1113
+ advanced?: BetterAuthAdvancedOptions | undefined;
1114
+ logger?: Logger | undefined;
1115
+ /**
1116
+ * allows you to define custom hooks that can be
1117
+ * executed during lifecycle of core database
1118
+ * operations.
1119
+ */
1120
+ databaseHooks?:
1121
+ | {
1122
+ /**
1123
+ * User hooks
1124
+ */
1125
+ user?: {
1126
+ create?: {
1127
+ /**
1128
+ * Hook that is called before a user is created.
1129
+ * if the hook returns false, the user will not be created.
1130
+ * If the hook returns an object, it'll be used instead of the original data
1131
+ */
1132
+ before?: (
1133
+ user: User & Record<string, unknown>,
1134
+ context: GenericEndpointContext | null,
1135
+ ) => Promise<
1136
+ | boolean
1137
+ | void
1138
+ | {
1139
+ data: Optional<User> & Record<string, any>;
1140
+ }
1141
+ >;
1142
+ /**
1143
+ * Hook that is called after a user is created.
1144
+ */
1145
+ after?: (
1146
+ user: User & Record<string, unknown>,
1147
+ context: GenericEndpointContext | null,
1148
+ ) => Promise<void>;
1149
+ };
1150
+ update?: {
1151
+ /**
1152
+ * Hook that is called before a user is updated.
1153
+ * if the hook returns false, the user will not be updated.
1154
+ * If the hook returns an object, it'll be used instead of the original data
1155
+ */
1156
+ before?: (
1157
+ user: Partial<User> & Record<string, unknown>,
1158
+ context: GenericEndpointContext | null,
1159
+ ) => Promise<
1160
+ | boolean
1161
+ | void
1162
+ | {
1163
+ data: Optional<User & Record<string, any>>;
1164
+ }
1165
+ >;
1166
+ /**
1167
+ * Hook that is called after a user is updated.
1168
+ */
1169
+ after?: (
1170
+ user: User & Record<string, unknown>,
1171
+ context: GenericEndpointContext | null,
1172
+ ) => Promise<void>;
1173
+ };
1174
+ delete?: {
1175
+ /**
1176
+ * Hook that is called before a user is deleted.
1177
+ * if the hook returns false, the user will not be deleted.
1178
+ */
1179
+ before?: (
1180
+ user: User & Record<string, unknown>,
1181
+ context: GenericEndpointContext | null,
1182
+ ) => Promise<boolean | void>;
1183
+ /**
1184
+ * Hook that is called after a user is deleted.
1185
+ */
1186
+ after?: (
1187
+ user: User & Record<string, unknown>,
1188
+ context: GenericEndpointContext | null,
1189
+ ) => Promise<void>;
1190
+ };
1191
+ };
1192
+ /**
1193
+ * Session Hook
1194
+ */
1195
+ session?: {
1196
+ create?: {
1197
+ /**
1198
+ * Hook that is called before a session is created.
1199
+ * if the hook returns false, the session will not be created.
1200
+ * If the hook returns an object, it'll be used instead of the original data
1201
+ */
1202
+ before?: (
1203
+ session: Session & Record<string, unknown>,
1204
+ context: GenericEndpointContext | null,
1205
+ ) => Promise<
1206
+ | boolean
1207
+ | void
1208
+ | {
1209
+ data: Optional<Session> & Record<string, any>;
1210
+ }
1211
+ >;
1212
+ /**
1213
+ * Hook that is called after a session is created.
1214
+ */
1215
+ after?: (
1216
+ session: Session & Record<string, unknown>,
1217
+ context: GenericEndpointContext | null,
1218
+ ) => Promise<void>;
1219
+ };
1220
+ /**
1221
+ * Update hook
1222
+ */
1223
+ update?: {
1224
+ /**
1225
+ * Hook that is called before a user is updated.
1226
+ * if the hook returns false, the session will not be updated.
1227
+ * If the hook returns an object, it'll be used instead of the original data
1228
+ */
1229
+ before?: (
1230
+ session: Partial<Session> & Record<string, unknown>,
1231
+ context: GenericEndpointContext | null,
1232
+ ) => Promise<
1233
+ | boolean
1234
+ | void
1235
+ | {
1236
+ data: Optional<Session & Record<string, any>>;
1237
+ }
1238
+ >;
1239
+ /**
1240
+ * Hook that is called after a session is updated.
1241
+ */
1242
+ after?: (
1243
+ session: Session & Record<string, unknown>,
1244
+ context: GenericEndpointContext | null,
1245
+ ) => Promise<void>;
1246
+ };
1247
+ delete?: {
1248
+ /**
1249
+ * Hook that is called before a session is deleted.
1250
+ * if the hook returns false, the session will not be deleted.
1251
+ */
1252
+ before?: (
1253
+ session: Session & Record<string, unknown>,
1254
+ context: GenericEndpointContext | null,
1255
+ ) => Promise<boolean | void>;
1256
+ /**
1257
+ * Hook that is called after a session is deleted.
1258
+ */
1259
+ after?: (
1260
+ session: Session & Record<string, unknown>,
1261
+ context: GenericEndpointContext | null,
1262
+ ) => Promise<void>;
1263
+ };
1264
+ };
1265
+ /**
1266
+ * Account Hook
1267
+ */
1268
+ account?: {
1269
+ create?: {
1270
+ /**
1271
+ * Hook that is called before a account is created.
1272
+ * If the hook returns false, the account will not be created.
1273
+ * If the hook returns an object, it'll be used instead of the original data
1274
+ */
1275
+ before?: (
1276
+ account: Account,
1277
+ context: GenericEndpointContext | null,
1278
+ ) => Promise<
1279
+ | boolean
1280
+ | void
1281
+ | {
1282
+ data: Optional<Account> & Record<string, any>;
1283
+ }
1284
+ >;
1285
+ /**
1286
+ * Hook that is called after a account is created.
1287
+ */
1288
+ after?: (
1289
+ account: Account,
1290
+ context: GenericEndpointContext | null,
1291
+ ) => Promise<void>;
1292
+ };
1293
+ /**
1294
+ * Update hook
1295
+ */
1296
+ update?: {
1297
+ /**
1298
+ * Hook that is called before a account is update.
1299
+ * If the hook returns false, the user will not be updated.
1300
+ * If the hook returns an object, it'll be used instead of the original data
1301
+ */
1302
+ before?: (
1303
+ account: Partial<Account> & Record<string, unknown>,
1304
+ context: GenericEndpointContext | null,
1305
+ ) => Promise<
1306
+ | boolean
1307
+ | void
1308
+ | {
1309
+ data: Optional<Account & Record<string, any>>;
1310
+ }
1311
+ >;
1312
+ /**
1313
+ * Hook that is called after a account is updated.
1314
+ */
1315
+ after?: (
1316
+ account: Account & Record<string, unknown>,
1317
+ context: GenericEndpointContext | null,
1318
+ ) => Promise<void>;
1319
+ };
1320
+ delete?: {
1321
+ /**
1322
+ * Hook that is called before an account is deleted.
1323
+ * if the hook returns false, the account will not be deleted.
1324
+ */
1325
+ before?: (
1326
+ account: Account & Record<string, unknown>,
1327
+ context: GenericEndpointContext | null,
1328
+ ) => Promise<boolean | void>;
1329
+ /**
1330
+ * Hook that is called after an account is deleted.
1331
+ */
1332
+ after?: (
1333
+ account: Account & Record<string, unknown>,
1334
+ context: GenericEndpointContext | null,
1335
+ ) => Promise<void>;
1336
+ };
1337
+ };
1338
+ /**
1339
+ * Verification Hook
1340
+ */
1341
+ verification?: {
1342
+ create?: {
1343
+ /**
1344
+ * Hook that is called before a verification is created.
1345
+ * if the hook returns false, the verification will not be created.
1346
+ * If the hook returns an object, it'll be used instead of the original data
1347
+ */
1348
+ before?: (
1349
+ verification: Verification & Record<string, unknown>,
1350
+ context: GenericEndpointContext | null,
1351
+ ) => Promise<
1352
+ | boolean
1353
+ | void
1354
+ | {
1355
+ data: Optional<Verification> & Record<string, any>;
1356
+ }
1357
+ >;
1358
+ /**
1359
+ * Hook that is called after a verification is created.
1360
+ */
1361
+ after?: (
1362
+ verification: Verification & Record<string, unknown>,
1363
+ context: GenericEndpointContext | null,
1364
+ ) => Promise<void>;
1365
+ };
1366
+ update?: {
1367
+ /**
1368
+ * Hook that is called before a verification is updated.
1369
+ * if the hook returns false, the verification will not be updated.
1370
+ * If the hook returns an object, it'll be used instead of the original data
1371
+ */
1372
+ before?: (
1373
+ verification: Partial<Verification> & Record<string, unknown>,
1374
+ context: GenericEndpointContext | null,
1375
+ ) => Promise<
1376
+ | boolean
1377
+ | void
1378
+ | {
1379
+ data: Optional<Verification & Record<string, any>>;
1380
+ }
1381
+ >;
1382
+ /**
1383
+ * Hook that is called after a verification is updated.
1384
+ */
1385
+ after?: (
1386
+ verification: Verification & Record<string, unknown>,
1387
+ context: GenericEndpointContext | null,
1388
+ ) => Promise<void>;
1389
+ };
1390
+ delete?: {
1391
+ /**
1392
+ * Hook that is called before a verification is deleted.
1393
+ * if the hook returns false, the verification will not be deleted.
1394
+ */
1395
+ before?: (
1396
+ verification: Verification & Record<string, unknown>,
1397
+ context: GenericEndpointContext | null,
1398
+ ) => Promise<boolean | void>;
1399
+ /**
1400
+ * Hook that is called after a verification is deleted.
1401
+ */
1402
+ after?: (
1403
+ verification: Verification & Record<string, unknown>,
1404
+ context: GenericEndpointContext | null,
1405
+ ) => Promise<void>;
1406
+ };
1407
+ };
1408
+ }
1409
+ | undefined;
1410
+ /**
1411
+ * API error handling
1412
+ */
1413
+ onAPIError?:
1414
+ | {
1415
+ /**
1416
+ * Throw an error on API error
1417
+ *
1418
+ * @default false
1419
+ */
1420
+ throw?: boolean;
1421
+ /**
1422
+ * Custom error handler
1423
+ *
1424
+ * @param error
1425
+ * @param ctx - Auth context
1426
+ */
1427
+ onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>;
1428
+ /**
1429
+ * The URL to redirect to on error
1430
+ *
1431
+ * When errorURL is provided, the error will be added to the URL as a query parameter
1432
+ * and the user will be redirected to the errorURL.
1433
+ *
1434
+ * @default - "/api/auth/error"
1435
+ */
1436
+ errorURL?: string;
1437
+ /**
1438
+ * Configure the default error page provided by Better-Auth
1439
+ * Start your dev server and go to /api/auth/error to see the error page.
1440
+ */
1441
+ customizeDefaultErrorPage?: {
1442
+ colors?: {
1443
+ background?: string;
1444
+ foreground?: string;
1445
+ primary?: string;
1446
+ primaryForeground?: string;
1447
+ mutedForeground?: string;
1448
+ border?: string;
1449
+ destructive?: string;
1450
+ titleBorder?: string;
1451
+ titleColor?: string;
1452
+ gridColor?: string;
1453
+ cardBackground?: string;
1454
+ cornerBorder?: string;
1455
+ };
1456
+ size?: {
1457
+ radiusSm?: string;
1458
+ radiusMd?: string;
1459
+ radiusLg?: string;
1460
+ textSm?: string;
1461
+ text2xl?: string;
1462
+ text4xl?: string;
1463
+ text6xl?: string;
1464
+ };
1465
+ font?: {
1466
+ defaultFamily?: string;
1467
+ monoFamily?: string;
1468
+ };
1469
+ disableTitleBorder?: boolean;
1470
+ disableCornerDecorations?: boolean;
1471
+ disableBackgroundGrid?: boolean;
1472
+ };
1473
+ }
1474
+ | undefined;
1475
+ /**
1476
+ * Hooks
1477
+ */
1478
+ hooks?:
1479
+ | {
1480
+ /**
1481
+ * Before a request is processed
1482
+ */
1483
+ before?: AuthMiddleware;
1484
+ /**
1485
+ * After a request is processed
1486
+ */
1487
+ after?: AuthMiddleware;
1488
+ }
1489
+ | undefined;
1490
+ /**
1491
+ * Disabled paths
1492
+ *
1493
+ * Paths you want to disable.
1494
+ */
1495
+ disabledPaths?: string[] | undefined;
1496
+ /**
1497
+ * Telemetry configuration
1498
+ */
1499
+ telemetry?:
1500
+ | {
1501
+ /**
1502
+ * Enable telemetry collection
1503
+ *
1504
+ * @default false
1505
+ */
1506
+ enabled?: boolean;
1507
+ /**
1508
+ * Enable debug mode
1509
+ *
1510
+ * @default false
1511
+ */
1512
+ debug?: boolean;
1513
+ }
1514
+ | undefined;
1515
+ /**
1516
+ * Experimental features
1517
+ */
1518
+ experimental?: {
1519
+ /**
1520
+ * Enable experimental joins for your database adapter.
1521
+ *
1522
+ * Please read the adapter documentation for more information regarding joins before enabling this.
1523
+ * Not all adapters support joins.
1524
+ *
1525
+ * @default false
1526
+ */
1527
+ joins?: boolean;
1528
+ };
1529
+ };