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