@better-auth/core 1.7.0-rc.4 → 1.7.0-rc.6

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 (113) hide show
  1. package/dist/api/index.d.mts +39 -60
  2. package/dist/api/index.mjs +39 -26
  3. package/dist/async_hooks/index.d.mts +1 -0
  4. package/dist/async_hooks/pure.index.d.mts +1 -0
  5. package/dist/context/endpoint-context.d.mts +1 -1
  6. package/dist/context/global.d.mts +1 -0
  7. package/dist/context/global.mjs +1 -1
  8. package/dist/context/request-state.d.mts +1 -0
  9. package/dist/context/transaction.d.mts +2 -3
  10. package/dist/db/adapter/factory.d.mts +5 -3
  11. package/dist/db/adapter/factory.mjs +1 -1
  12. package/dist/db/adapter/get-default-field-name.d.mts +9 -2
  13. package/dist/db/adapter/get-default-model-name.d.mts +5 -1
  14. package/dist/db/adapter/get-field-attributes.d.mts +11 -4
  15. package/dist/db/adapter/get-field-name.d.mts +9 -2
  16. package/dist/db/adapter/get-id-field.d.mts +12 -4
  17. package/dist/db/adapter/get-model-name.d.mts +5 -1
  18. package/dist/db/adapter/index.d.mts +32 -7
  19. package/dist/db/adapter/types.d.mts +17 -5
  20. package/dist/db/adapter/utils.d.mts +1 -0
  21. package/dist/db/database-index.d.mts +12 -2
  22. package/dist/db/get-tables.d.mts +0 -1
  23. package/dist/db/plugin.d.mts +3 -3
  24. package/dist/db/schema/account.d.mts +1 -1
  25. package/dist/db/schema/rate-limit.d.mts +1 -1
  26. package/dist/db/schema/session.d.mts +1 -1
  27. package/dist/db/schema/shared.d.mts +1 -0
  28. package/dist/db/schema/user.d.mts +1 -1
  29. package/dist/db/schema/verification.d.mts +1 -1
  30. package/dist/db/type.d.mts +11 -8
  31. package/dist/env/logger.d.mts +25 -25
  32. package/dist/error/codes.d.mts +1 -0
  33. package/dist/error/index.d.mts +1 -0
  34. package/dist/index.d.mts +1 -1
  35. package/dist/instrumentation/attributes.d.mts +1 -0
  36. package/dist/instrumentation/pure.index.d.mts +1 -0
  37. package/dist/instrumentation/tracer.mjs +1 -1
  38. package/dist/oauth2/authorization-params.d.mts +1 -0
  39. package/dist/oauth2/client-assertion.d.mts +13 -3
  40. package/dist/oauth2/client-credentials-token.d.mts +17 -3
  41. package/dist/oauth2/create-authorization-url.d.mts +21 -3
  42. package/dist/oauth2/dpop.d.mts +23 -2
  43. package/dist/oauth2/dpop.mjs +1 -1
  44. package/dist/oauth2/oauth-provider.d.mts +7 -13
  45. package/dist/oauth2/refresh-access-token.d.mts +19 -3
  46. package/dist/oauth2/refresh-access-token.mjs +1 -1
  47. package/dist/oauth2/reject-redirects.mjs +1 -1
  48. package/dist/oauth2/token-endpoint-auth.d.mts +1 -0
  49. package/dist/oauth2/utils.d.mts +1 -0
  50. package/dist/oauth2/utils.mjs +1 -1
  51. package/dist/oauth2/validate-authorization-code.d.mts +29 -5
  52. package/dist/oauth2/verify-id-token.d.mts +1 -1
  53. package/dist/oauth2/verify.d.mts +7 -5
  54. package/dist/oauth2/verify.mjs +2 -2
  55. package/dist/social-providers/apple.d.mts +18 -5
  56. package/dist/social-providers/atlassian.d.mts +15 -4
  57. package/dist/social-providers/cognito.d.mts +18 -5
  58. package/dist/social-providers/discord.d.mts +13 -4
  59. package/dist/social-providers/dropbox.d.mts +15 -4
  60. package/dist/social-providers/facebook.d.mts +18 -6
  61. package/dist/social-providers/figma.d.mts +15 -4
  62. package/dist/social-providers/github.d.mts +16 -4
  63. package/dist/social-providers/gitlab.d.mts +16 -4
  64. package/dist/social-providers/google.d.mts +25 -6
  65. package/dist/social-providers/huggingface.d.mts +15 -4
  66. package/dist/social-providers/index.d.mts +504 -113
  67. package/dist/social-providers/kakao.d.mts +13 -4
  68. package/dist/social-providers/kick.d.mts +15 -4
  69. package/dist/social-providers/line.d.mts +16 -4
  70. package/dist/social-providers/linear.d.mts +14 -4
  71. package/dist/social-providers/linkedin.d.mts +14 -4
  72. package/dist/social-providers/microsoft-entra-id.d.mts +14 -5
  73. package/dist/social-providers/microsoft-entra-id.mjs +1 -2
  74. package/dist/social-providers/naver.d.mts +22 -23
  75. package/dist/social-providers/notion.d.mts +14 -4
  76. package/dist/social-providers/paybin.d.mts +16 -4
  77. package/dist/social-providers/paypal.d.mts +13 -4
  78. package/dist/social-providers/polar.d.mts +15 -4
  79. package/dist/social-providers/railway.d.mts +15 -4
  80. package/dist/social-providers/reddit.d.mts +13 -4
  81. package/dist/social-providers/roblox.d.mts +13 -4
  82. package/dist/social-providers/salesforce.d.mts +15 -4
  83. package/dist/social-providers/slack.d.mts +13 -4
  84. package/dist/social-providers/spotify.d.mts +15 -4
  85. package/dist/social-providers/tiktok.d.mts +14 -6
  86. package/dist/social-providers/twitch.d.mts +13 -4
  87. package/dist/social-providers/twitter.d.mts +19 -26
  88. package/dist/social-providers/vercel.d.mts +15 -4
  89. package/dist/social-providers/vk.d.mts +16 -4
  90. package/dist/social-providers/wechat.d.mts +12 -4
  91. package/dist/social-providers/zoom.d.mts +18 -6
  92. package/dist/types/context.d.mts +2 -2
  93. package/dist/types/cookie.d.mts +1 -1
  94. package/dist/types/helper.d.mts +1 -1
  95. package/dist/types/index.d.mts +1 -1
  96. package/dist/types/init-options.d.mts +18 -26
  97. package/dist/types/plugin-client.d.mts +3 -1
  98. package/dist/types/plugin.d.mts +2 -2
  99. package/dist/utils/async.d.mts +1 -0
  100. package/dist/utils/db.d.mts +0 -1
  101. package/dist/utils/deprecate.d.mts +1 -0
  102. package/dist/utils/email.d.mts +4 -1
  103. package/dist/utils/error-codes.d.mts +2 -2
  104. package/dist/utils/host.d.mts +1 -27
  105. package/dist/utils/host.mjs +1 -1
  106. package/dist/utils/ip.d.mts +0 -1
  107. package/dist/utils/ip.mjs +1 -1
  108. package/dist/utils/is-api-error.d.mts +1 -0
  109. package/dist/utils/redirect-uri.d.mts +1 -0
  110. package/package.json +4 -4
  111. package/src/api/index.ts +96 -95
  112. package/src/db/type.ts +2 -1
  113. package/src/types/init-options.ts +6 -4
@@ -26,33 +26,7 @@
26
26
  * The semantic kind of a host, derived from RFC 6890 special-purpose registries
27
27
  * plus a few domain-name categories (localhost, cloud metadata FQDNs).
28
28
  */
29
- type HostKind =
30
- /** IPv4 `127.0.0.0/8` or IPv6 `::1`. */
31
- "loopback" |
32
- /** DNS name `localhost` or RFC 6761 `.localhost` TLD. */
33
- "localhost" |
34
- /** IPv4 `0.0.0.0` or IPv6 `::` — "this host on this network", not loopback. */
35
- "unspecified" |
36
- /** RFC 1918 `10/8`, `172.16/12`, `192.168/16`, or IPv6 ULA `fc00::/7`. */
37
- "private" |
38
- /** IPv4 `169.254/16` or IPv6 `fe80::/10`. Includes AWS IMDS `169.254.169.254`. */
39
- "linkLocal" |
40
- /** RFC 6598 carrier-grade NAT `100.64.0.0/10`. */
41
- "sharedAddressSpace" |
42
- /** RFC 5737 `192.0.2/24`, `198.51.100/24`, `203.0.113/24`, or RFC 3849 `2001:db8::/32`. */
43
- "documentation" |
44
- /** RFC 2544 `198.18.0.0/15`. */
45
- "benchmarking" |
46
- /** IPv4 `224.0.0.0/4` or IPv6 `ff00::/8`. */
47
- "multicast" |
48
- /** IPv4 limited broadcast `255.255.255.255`. */
49
- "broadcast" |
50
- /** Other RFC 6890 special-purpose ranges (0.0.0.0/8, 192.0.0.0/24, 192.88.99.0/24, 240.0.0.0/4, 2001::/32, etc.). */
51
- "reserved" |
52
- /** Cloud metadata service FQDN (e.g. `metadata.google.internal`). */
53
- "cloudMetadata" |
54
- /** Any host not matching a special-purpose range above. */
55
- "public";
29
+ type HostKind = /** IPv4 `127.0.0.0/8` or IPv6 `::1`. */"loopback" /** DNS name `localhost` or RFC 6761 `.localhost` TLD. */ | "localhost" /** IPv4 `0.0.0.0` or IPv6 `::` — "this host on this network", not loopback. */ | "unspecified" /** RFC 1918 `10/8`, `172.16/12`, `192.168/16`, or IPv6 ULA `fc00::/7`. */ | "private" /** IPv4 `169.254/16` or IPv6 `fe80::/10`. Includes AWS IMDS `169.254.169.254`. */ | "linkLocal" /** RFC 6598 carrier-grade NAT `100.64.0.0/10`. */ | "sharedAddressSpace" /** RFC 5737 `192.0.2/24`, `198.51.100/24`, `203.0.113/24`, or RFC 3849 `2001:db8::/32`. */ | "documentation" /** RFC 2544 `198.18.0.0/15`. */ | "benchmarking" /** IPv4 `224.0.0.0/4` or IPv6 `ff00::/8`. */ | "multicast" /** IPv4 limited broadcast `255.255.255.255`. */ | "broadcast" /** Other RFC 6890 special-purpose ranges (0.0.0.0/8, 192.0.0.0/24, 192.88.99.0/24, 240.0.0.0/4, 2001::/32, etc.). */ | "reserved" /** Cloud metadata service FQDN (e.g. `metadata.google.internal`). */ | "cloudMetadata" /** Any host not matching a special-purpose range above. */ | "public";
56
30
  /**
57
31
  * The syntactic form of the input host: an IPv4 literal, an IPv6 literal, or
58
32
  * a domain name. IPv4-mapped IPv6 (`::ffff:192.0.2.1`) is reported as `ipv4`
@@ -9,7 +9,7 @@ import { isValidIP, normalizeIP } from "./ip.mjs";
9
9
  * only exists for the FQDN form that a naive server-side fetch might resolve
10
10
  * via its own resolver.
11
11
  */
12
- const CLOUD_METADATA_HOSTS = /* @__PURE__ */ new Set([
12
+ const CLOUD_METADATA_HOSTS = new Set([
13
13
  "metadata.google.internal",
14
14
  "metadata.goog",
15
15
  "metadata",
@@ -1,5 +1,4 @@
1
1
  import { BetterAuthOptions } from "../types/init-options.mjs";
2
- import "../types/index.mjs";
3
2
  //#region src/utils/ip.d.ts
4
3
  /**
5
4
  * Normalizes an IP address for consistent rate limiting.
package/dist/utils/ip.mjs CHANGED
@@ -111,7 +111,7 @@ function ipToBytes(ip) {
111
111
  const mapped = extractIPv4FromMapped(ip);
112
112
  if (mapped) return Uint8Array.from(mapped.split(".").map((octet) => Number(octet)));
113
113
  const groups = expandIPv6(ip);
114
- const bytes = /* @__PURE__ */ new Uint8Array(16);
114
+ const bytes = new Uint8Array(16);
115
115
  for (let i = 0; i < 8; i++) {
116
116
  const group = Number.parseInt(groups[i] ?? "0", 16);
117
117
  bytes[i * 2] = group >> 8 & 255;
@@ -1,4 +1,5 @@
1
1
  import { APIError } from "../error/index.mjs";
2
+
2
3
  //#region src/utils/is-api-error.d.ts
3
4
  declare function isAPIError(error: unknown): error is APIError;
4
5
  //#endregion
@@ -1,4 +1,5 @@
1
1
  import * as z from "zod";
2
+
2
3
  //#region src/utils/redirect-uri.d.ts
3
4
  /**
4
5
  * Returns whether a parsed redirect URI uses an authority-free, reverse-domain
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/core",
3
- "version": "1.7.0-rc.4",
3
+ "version": "1.7.0-rc.6",
4
4
  "description": "The most comprehensive authentication framework for TypeScript.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -166,18 +166,18 @@
166
166
  "@opentelemetry/api": "^1.9.1",
167
167
  "@opentelemetry/sdk-trace-base": "^2.10.0",
168
168
  "@opentelemetry/sdk-trace-node": "^2.10.0",
169
- "better-call": "1.3.7",
169
+ "better-call": "1.4.0",
170
170
  "jose": "^6.2.3",
171
171
  "kysely": "^0.28.17 || ^0.29.0",
172
172
  "nanostores": "^1.3.0",
173
- "tsdown": "0.22.7"
173
+ "tsdown": "0.21.10"
174
174
  },
175
175
  "peerDependencies": {
176
176
  "@better-auth/utils": "0.4.2",
177
177
  "@better-fetch/fetch": "1.3.1",
178
178
  "@cloudflare/workers-types": ">=4",
179
179
  "@opentelemetry/api": "^1.9.0",
180
- "better-call": "1.3.7",
180
+ "better-call": "1.4.0",
181
181
  "jose": "^6.1.0",
182
182
  "kysely": "^0.28.5 || ^0.29.0",
183
183
  "nanostores": "^1.0.1"
package/src/api/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type {
2
- EndpointContext,
2
+ EndpointHandler,
3
3
  EndpointOptions,
4
+ MiddlewareHandler,
4
5
  StrictEndpoint,
5
6
  } from "better-call";
6
7
  import {
@@ -75,94 +76,93 @@ export const createAuthMiddleware = createMiddleware.create({
75
76
  ],
76
77
  });
77
78
 
78
- const use = [optionsMiddleware];
79
+ const createEndpointWithAuthContext = createEndpoint.create({
80
+ use: [optionsMiddleware],
81
+ });
79
82
 
80
- type EndpointHandler<
83
+ type AuthEndpointHandler<
81
84
  Path extends string,
82
85
  Options extends EndpointOptions,
83
86
  R,
84
- > = (context: EndpointContext<Path, Options, AuthContext>) => Promise<R>;
87
+ > = EndpointHandler<Path, Options, R, AuthContext>;
85
88
 
86
- export function createAuthEndpoint<
87
- Path extends string,
89
+ type PathlessAuthEndpointHandler<
88
90
  Options extends EndpointOptions,
89
91
  R,
90
- >(
91
- path: Path,
92
- options: Options,
93
- handler: EndpointHandler<Path, Options, R>,
94
- ): StrictEndpoint<Path, Options, R>;
92
+ > = AuthEndpointHandler<string, Options, R>;
95
93
 
96
- export function createAuthEndpoint<
94
+ function wrapEndpointHandler<
97
95
  Path extends string,
98
96
  Options extends EndpointOptions,
99
97
  R,
100
98
  >(
99
+ handler: AuthEndpointHandler<Path, Options, R>,
101
100
  options: Options,
102
- handler: EndpointHandler<Path, Options, R>,
103
- ): StrictEndpoint<Path, Options, R>;
104
-
105
- export function createAuthEndpoint<
106
- Path extends string,
107
- Opts extends EndpointOptions,
108
- R,
109
- >(
110
- pathOrOptions: Path | Opts,
111
- handlerOrOptions: EndpointHandler<Path, Opts, R> | Opts,
112
- handlerOrNever?: any,
113
- ) {
114
- const path: Path | undefined =
115
- typeof pathOrOptions === "string" ? pathOrOptions : undefined;
116
- const options: Opts =
117
- typeof handlerOrOptions === "object"
118
- ? handlerOrOptions
119
- : (pathOrOptions as Opts);
120
- const handler: EndpointHandler<Path, Opts, R> =
121
- typeof handlerOrOptions === "function" ? handlerOrOptions : handlerOrNever;
122
-
123
- // Endpoints that return credentials declare `metadata: { noStore: true }`.
124
- // Emit the no-store headers at the boundary, before the handler runs, so they
125
- // land on every response the handler produces: a success harvests
126
- // `responseHeaders`, and a thrown error carries the same headers through
127
- // `attachResponseHeadersToAPIError`. Validation that rejects the request
128
- // before the handler runs is not covered (and returns no credentials).
101
+ ): AuthEndpointHandler<Path, Options, R> {
129
102
  const noStore =
130
103
  (options as { metadata?: { noStore?: boolean } }).metadata?.noStore ===
131
104
  true;
132
105
 
133
- // todo: prettify the code, we want to call `runWithEndpointContext` to top level
134
- const wrapped: EndpointHandler<Path, Opts, R> = async (ctx) => {
106
+ return async (context) => {
135
107
  if (noStore) {
136
108
  for (const [name, value] of Object.entries(NO_STORE_HEADERS)) {
137
- ctx.setHeader(name, value);
109
+ context.setHeader(name, value);
138
110
  }
139
111
  }
140
- const runtimeCtx = ctx as unknown as { responseHeaders?: Headers };
141
112
  try {
142
- return await runWithEndpointContext(ctx as any, () => handler(ctx));
143
- } catch (e) {
144
- attachResponseHeadersToAPIError(runtimeCtx.responseHeaders, e);
145
- throw e;
113
+ return await runWithEndpointContext(context, () => handler(context));
114
+ } catch (error) {
115
+ attachResponseHeadersToAPIError(context.responseHeaders, error);
116
+ throw error;
146
117
  }
147
118
  };
119
+ }
148
120
 
149
- if (path) {
150
- return createEndpoint(
121
+ export function createAuthEndpoint<
122
+ Path extends string,
123
+ Options extends EndpointOptions,
124
+ R,
125
+ >(
126
+ path: Path,
127
+ options: Options,
128
+ handler: AuthEndpointHandler<Path, Options, R>,
129
+ ): StrictEndpoint<Path, Options, R>;
130
+
131
+ export function createAuthEndpoint<
132
+ InferredPath extends string,
133
+ Options extends EndpointOptions,
134
+ R,
135
+ >(
136
+ options: Options,
137
+ handler: PathlessAuthEndpointHandler<Options, R>,
138
+ ): StrictEndpoint<InferredPath, Options, R>;
139
+
140
+ export function createAuthEndpoint<
141
+ Path extends string,
142
+ Options extends EndpointOptions,
143
+ R,
144
+ >(
145
+ ...args:
146
+ | [
147
+ path: Path,
148
+ options: Options,
149
+ handler: AuthEndpointHandler<Path, Options, R>,
150
+ ]
151
+ | [options: Options, handler: PathlessAuthEndpointHandler<Options, R>]
152
+ ) {
153
+ if (args.length === 3) {
154
+ const [path, options, handler] = args;
155
+ return createEndpointWithAuthContext(
151
156
  path,
152
- {
153
- ...options,
154
- use: [...(options?.use || []), ...use],
155
- },
156
- wrapped,
157
+ options,
158
+ wrapEndpointHandler(handler, options),
157
159
  );
158
160
  }
159
161
 
160
- return createEndpoint(
161
- {
162
- ...options,
163
- use: [...(options?.use || []), ...use],
164
- },
165
- wrapped,
162
+ const [options, handler] = args;
163
+ return createEndpointWithAuthContext(
164
+ options,
165
+ wrapEndpointHandler(handler, options),
166
166
  );
167
167
  }
168
168
 
@@ -179,44 +179,45 @@ function withServerOnly<Options extends EndpointOptions>(
179
179
  } as Options;
180
180
  }
181
181
 
182
- export namespace createAuthEndpoint {
183
- /**
184
- * Declare a **server-only** endpoint.
185
- *
186
- * The endpoint is callable through `auth.api.*` from trusted server code but is
187
- * never registered on the HTTP router and never emitted into the OpenAPI
188
- * schema. It takes no path because it has no URL to be reached at.
189
- *
190
- * Prefer this over the path-less `createAuthEndpoint({ ... }, handler)` form.
191
- * Setting `metadata.SERVER_ONLY` makes the intent explicit at the call site and
192
- * keeps the endpoint off the HTTP surface even if a path is later added by
193
- * mistake: better-call's router skips an endpoint when its path is missing *or*
194
- * when `SERVER_ONLY` is set, so the two together are defense in depth. Relying
195
- * on path omission alone is invisible and one keystroke away from exposure.
196
- *
197
- * @example
198
- * ```ts
199
- * viewBackupCodes: createAuthEndpoint.serverOnly(
200
- * { method: "POST", body: schema },
201
- * async (ctx) => { ... },
202
- * )
203
- * ```
204
- */
205
- export function serverOnly<
206
- Path extends string,
207
- Options extends EndpointOptions,
208
- R,
209
- >(
210
- options: Options,
211
- handler: EndpointHandler<Path, Options, R>,
212
- ): StrictEndpoint<Path, Options, R> {
213
- return createAuthEndpoint(withServerOnly(options), handler);
214
- }
215
- }
182
+ /**
183
+ * Declare a **server-only** endpoint.
184
+ *
185
+ * The endpoint is callable through `auth.api.*` from trusted server code but is
186
+ * never registered on the HTTP router and never emitted into the OpenAPI
187
+ * schema. It takes no path because it has no URL to be reached at.
188
+ *
189
+ * Prefer this over the path-less `createAuthEndpoint({ ... }, handler)` form.
190
+ * Setting `metadata.SERVER_ONLY` makes the intent explicit at the call site and
191
+ * keeps the endpoint off the HTTP surface even if a path is later added by
192
+ * mistake: better-call's router skips an endpoint when its path is missing *or*
193
+ * when `SERVER_ONLY` is set, so the two together are defense in depth. Relying
194
+ * on path omission alone is invisible and one keystroke away from exposure.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * viewBackupCodes: createAuthEndpoint.serverOnly(
199
+ * { method: "POST", body: schema },
200
+ * async (ctx) => { ... },
201
+ * )
202
+ * ```
203
+ */
204
+ createAuthEndpoint.serverOnly = <
205
+ InferredPath extends string,
206
+ Options extends EndpointOptions,
207
+ R,
208
+ >(
209
+ options: Options,
210
+ handler: PathlessAuthEndpointHandler<Options, R>,
211
+ ): StrictEndpoint<InferredPath, Options, R> =>
212
+ createAuthEndpoint<InferredPath, Options, R>(
213
+ withServerOnly(options),
214
+ handler,
215
+ );
216
216
 
217
217
  export type AuthEndpoint<
218
218
  Path extends string,
219
219
  Opts extends EndpointOptions,
220
220
  R,
221
221
  > = ReturnType<typeof createAuthEndpoint<Path, Opts, R>>;
222
- export type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
222
+
223
+ export type AuthMiddleware = MiddlewareHandler;
package/src/db/type.ts CHANGED
@@ -251,7 +251,8 @@ export type DBFieldAttributeConfig = {
251
251
  */
252
252
  bigint?: boolean | undefined;
253
253
  /**
254
- * A zod schema to validate the value.
254
+ * A Standard Schema to validate the value. Works with any Standard Schema
255
+ * library, such as Zod, Valibot or ArkType.
255
256
  */
256
257
  validator?:
257
258
  | {
@@ -146,7 +146,8 @@ export type DynamicBaseURLConfig = {
146
146
  /**
147
147
  * List of allowed hostnames. Supports wildcard patterns.
148
148
  *
149
- * The derived host from the request will be validated against this list.
149
+ * `x-forwarded-host` is used only when `advanced.trustedProxyHeaders` is
150
+ * enabled.
150
151
  * Uses the same wildcard matching as `trustedOrigins`.
151
152
  *
152
153
  * @example
@@ -161,8 +162,9 @@ export type DynamicBaseURLConfig = {
161
162
  allowedHosts: string[];
162
163
 
163
164
  /**
164
- * Fallback URL to use if the derived host doesn't match any allowed host.
165
- * If not set, Better Auth will throw an error when the host doesn't match.
165
+ * Fallback URL used when no allowed request host can be resolved.
166
+ * If omitted, Better Auth throws when the request host is unavailable or not
167
+ * allowed.
166
168
  *
167
169
  * @example "https://myapp.com"
168
170
  */
@@ -172,7 +174,7 @@ export type DynamicBaseURLConfig = {
172
174
  * Protocol to use when constructing the URL.
173
175
  * - `"https"`: Always use HTTPS (recommended for production)
174
176
  * - `"http"`: Always use HTTP (for local development)
175
- * - `"auto"`: Derive from `x-forwarded-proto` header or default to HTTPS
177
+ * - `"auto"`: Trust `x-forwarded-proto` only when proxy headers are enabled
176
178
  *
177
179
  * @default "auto"
178
180
  */