better-auth 1.7.0-beta.4 → 1.7.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/api/dispatch.d.mts +34 -0
  2. package/dist/api/dispatch.mjs +272 -0
  3. package/dist/api/index.d.mts +27 -10
  4. package/dist/api/index.mjs +3 -2
  5. package/dist/api/middlewares/origin-check.mjs +1 -0
  6. package/dist/api/routes/account.d.mts +10 -4
  7. package/dist/api/routes/account.mjs +73 -82
  8. package/dist/api/routes/callback.mjs +62 -38
  9. package/dist/api/routes/session.mjs +4 -2
  10. package/dist/api/routes/sign-in.d.mts +2 -0
  11. package/dist/api/routes/sign-in.mjs +39 -18
  12. package/dist/api/routes/sign-up.mjs +39 -33
  13. package/dist/api/routes/update-session.mjs +9 -3
  14. package/dist/api/state/oauth.d.mts +38 -2
  15. package/dist/api/state/oauth.mjs +35 -2
  16. package/dist/api/to-auth-endpoints.mjs +14 -265
  17. package/dist/auth/trusted-origins.mjs +60 -1
  18. package/dist/client/lynx/index.d.mts +6 -5
  19. package/dist/client/react/index.d.mts +6 -5
  20. package/dist/client/solid/index.d.mts +6 -5
  21. package/dist/client/svelte/index.d.mts +6 -5
  22. package/dist/client/vanilla.d.mts +6 -5
  23. package/dist/client/vue/index.d.mts +6 -5
  24. package/dist/context/create-context.mjs +1 -1
  25. package/dist/cookies/cookie-utils.mjs +2 -2
  26. package/dist/cookies/index.mjs +7 -2
  27. package/dist/cookies/session-store.d.mts +1 -1
  28. package/dist/db/get-migration.mjs +34 -1
  29. package/dist/db/internal-adapter.mjs +89 -25
  30. package/dist/db/schema.d.mts +1 -1
  31. package/dist/db/to-zod.d.mts +2 -2
  32. package/dist/db/to-zod.mjs +1 -1
  33. package/dist/index.d.mts +3 -3
  34. package/dist/oauth2/errors.mjs +21 -1
  35. package/dist/oauth2/index.d.mts +6 -4
  36. package/dist/oauth2/index.mjs +5 -3
  37. package/dist/oauth2/persist-account.d.mts +80 -0
  38. package/dist/oauth2/persist-account.mjs +84 -0
  39. package/dist/oauth2/resolve-account.d.mts +126 -0
  40. package/dist/oauth2/resolve-account.mjs +128 -0
  41. package/dist/oauth2/sign-in-with-oauth-identity.d.mts +83 -0
  42. package/dist/oauth2/sign-in-with-oauth-identity.mjs +133 -0
  43. package/dist/oauth2/state.d.mts +31 -5
  44. package/dist/oauth2/state.mjs +11 -7
  45. package/dist/oauth2/{utils.d.mts → token-encryption.d.mts} +1 -1
  46. package/dist/oauth2/{utils.mjs → token-encryption.mjs} +1 -1
  47. package/dist/packages/better-auth/package.mjs +1 -1
  48. package/dist/plugins/admin/access/statement.d.mts +10 -10
  49. package/dist/plugins/admin/access/statement.mjs +2 -0
  50. package/dist/plugins/admin/admin.d.mts +6 -3
  51. package/dist/plugins/admin/client.d.mts +6 -4
  52. package/dist/plugins/admin/error-codes.d.mts +2 -0
  53. package/dist/plugins/admin/error-codes.mjs +3 -1
  54. package/dist/plugins/admin/routes.mjs +67 -3
  55. package/dist/plugins/admin/schema.d.mts +1 -0
  56. package/dist/plugins/admin/schema.mjs +2 -1
  57. package/dist/plugins/anonymous/index.d.mts +4 -0
  58. package/dist/plugins/anonymous/index.mjs +90 -47
  59. package/dist/plugins/email-otp/routes.mjs +2 -2
  60. package/dist/plugins/generic-oauth/index.d.mts +2 -2
  61. package/dist/plugins/generic-oauth/index.mjs +31 -7
  62. package/dist/plugins/generic-oauth/types.d.mts +13 -0
  63. package/dist/plugins/jwt/sign.d.mts +11 -0
  64. package/dist/plugins/jwt/sign.mjs +2 -1
  65. package/dist/plugins/jwt/types.d.mts +9 -1
  66. package/dist/plugins/magic-link/index.mjs +14 -6
  67. package/dist/plugins/oauth-proxy/index.mjs +30 -6
  68. package/dist/plugins/one-tap/index.mjs +26 -10
  69. package/dist/plugins/open-api/generator.d.mts +4 -1
  70. package/dist/plugins/open-api/generator.mjs +5 -1
  71. package/dist/plugins/organization/adapter.mjs +2 -0
  72. package/dist/plugins/organization/organization.mjs +2 -0
  73. package/dist/plugins/organization/routes/crud-access-control.d.mts +1 -1
  74. package/dist/plugins/organization/routes/crud-invites.mjs +40 -5
  75. package/dist/plugins/organization/routes/crud-team.mjs +13 -1
  76. package/dist/plugins/organization/schema.d.mts +2 -0
  77. package/dist/plugins/organization/types.d.mts +18 -11
  78. package/dist/plugins/phone-number/routes.mjs +1 -1
  79. package/dist/plugins/siwe/index.mjs +29 -1
  80. package/dist/plugins/siwe/parse-message.mjs +60 -0
  81. package/dist/plugins/test-utils/db-helpers.mjs +1 -1
  82. package/dist/plugins/two-factor/index.mjs +9 -1
  83. package/dist/state.d.mts +17 -1
  84. package/dist/state.mjs +4 -2
  85. package/dist/test-utils/http-test-instance.d.mts +26 -5
  86. package/dist/test-utils/test-instance.d.mts +107 -37
  87. package/dist/types/index.d.mts +2 -2
  88. package/dist/utils/index.d.mts +1 -1
  89. package/dist/utils/validate-user-info.mjs +44 -0
  90. package/package.json +10 -10
  91. package/dist/oauth2/error-codes.mjs +0 -20
  92. package/dist/oauth2/link-account.d.mts +0 -72
  93. package/dist/oauth2/link-account.mjs +0 -164
@@ -0,0 +1,34 @@
1
+ import { AuthContext } from "@better-auth/core";
2
+ import { Endpoint, EndpointContext, InputContext } from "better-call";
3
+
4
+ //#region src/api/dispatch.d.ts
5
+ /**
6
+ * Input accepted by {@link dispatchAuthEndpoint}. `context` must already be a
7
+ * resolved `AuthContext`; the caller owns `baseURL` resolution. A fresh
8
+ * dispatch carries no `session` (the shared context has none), while a resumed
9
+ * dispatch carries the in-flight request's `session` through.
10
+ */
11
+ type DispatchContext = Partial<InputContext<string, any> & EndpointContext<string, any>> & {
12
+ context: AuthContext & {
13
+ returned?: unknown | undefined;
14
+ responseHeaders?: Headers | undefined;
15
+ };
16
+ operationId?: string | undefined;
17
+ };
18
+ /**
19
+ * Run a single endpoint through the configured `hooks.before` / `hooks.after`
20
+ * pipeline, normalizing the response, headers, and `APIError`s the same way a
21
+ * router or `auth.api.*` dispatch does.
22
+ *
23
+ * This is the canonical hook runner. The HTTP router and `auth.api.*` reach it
24
+ * through {@link toAuthEndpoints}. Plugins call it directly when they need to
25
+ * re-enter the pipeline on purpose, such as resuming `/oauth2/authorize` after
26
+ * a fresh sign-in. Calling an endpoint as a plain function deliberately skips
27
+ * hooks; `dispatchAuthEndpoint` is the supported way to opt back in.
28
+ *
29
+ * @param endpoint The endpoint to dispatch.
30
+ * @param input Input context whose `context` is an already-resolved `AuthContext`.
31
+ */
32
+ declare function dispatchAuthEndpoint(endpoint: Endpoint, input: DispatchContext): Promise<unknown>;
33
+ //#endregion
34
+ export { DispatchContext, dispatchAuthEndpoint };
@@ -0,0 +1,272 @@
1
+ import { isAPIError } from "../utils/is-api-error.mjs";
2
+ import { isRequestLike } from "../utils/url.mjs";
3
+ import { runWithEndpointContext } from "@better-auth/core/context";
4
+ import { shouldPublishLog } from "@better-auth/core/env";
5
+ import { APIError } from "@better-auth/core/error";
6
+ import { createDefu } from "defu";
7
+ import { ATTR_CONTEXT, ATTR_HOOK_TYPE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, withSpan } from "@better-auth/core/instrumentation";
8
+ import { kAPIErrorHeaderSymbol, toResponse } from "better-call";
9
+ //#region src/api/dispatch.ts
10
+ const defuReplaceArrays = createDefu((obj, key, value) => {
11
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
12
+ obj[key] = value;
13
+ return true;
14
+ }
15
+ });
16
+ const hooksSourceWeakMap = /* @__PURE__ */ new WeakMap();
17
+ /**
18
+ * Resolves the operation id used for spans, preferring an explicit
19
+ * `operationId`, then the OpenAPI one, then the caller's `fallback` (the
20
+ * `auth.api.*` map key), and finally the route path.
21
+ */
22
+ function getOperationId(endpoint, fallback) {
23
+ const opts = endpoint.options;
24
+ return opts?.operationId ?? opts?.metadata?.openapi?.operationId ?? fallback ?? endpoint.path ?? "/:virtual";
25
+ }
26
+ /**
27
+ * Merge a set of response headers onto the dispatch's accumulator, appending
28
+ * `set-cookie` (multiple cookies are legal) and replacing everything else.
29
+ */
30
+ function mergeResponseHeaders(context, headers) {
31
+ if (!headers) return;
32
+ headers.forEach((value, key) => {
33
+ if (!context.responseHeaders) context.responseHeaders = new Headers({ [key]: value });
34
+ else if (key.toLowerCase() === "set-cookie") context.responseHeaders.append(key, value);
35
+ else context.responseHeaders.set(key, value);
36
+ });
37
+ }
38
+ /**
39
+ * Combine the two header sources an `APIError` can carry into one set:
40
+ * - `kAPIErrorHeaderSymbol`: `ctx.responseHeaders` accumulated via
41
+ * `c.setCookie` / `c.setHeader` before the throw.
42
+ * - `e.headers`: explicit headers on the error (e.g. `location` from
43
+ * `c.redirect`).
44
+ *
45
+ * `c.redirect()` reuses `ctx.responseHeaders` as `e.headers`, so when both
46
+ * point at the same object iterating each would duplicate every `set-cookie`;
47
+ * the identity check skips that copy. Explicit error headers override
48
+ * accumulated ones, while cookies from both accumulate.
49
+ */
50
+ function mergeAPIErrorHeaders(error) {
51
+ const ctxHeaders = error[kAPIErrorHeaderSymbol];
52
+ const errHeaders = error.headers && error.headers !== ctxHeaders ? new Headers(error.headers) : null;
53
+ if (!ctxHeaders && !errHeaders) return null;
54
+ const headers = new Headers();
55
+ ctxHeaders?.forEach((value, key) => {
56
+ headers.append(key, value);
57
+ });
58
+ errHeaders?.forEach((value, key) => {
59
+ if (key.toLowerCase() === "set-cookie") headers.append(key, value);
60
+ else headers.set(key, value);
61
+ });
62
+ return headers;
63
+ }
64
+ async function runBeforeHooks(context, hooks, endpoint, operationId) {
65
+ let modifiedContext = {};
66
+ for (const hook of hooks) {
67
+ let matched = false;
68
+ try {
69
+ matched = hook.matcher(context);
70
+ } catch (error) {
71
+ const hookSource = hooksSourceWeakMap.get(hook.handler) ?? "unknown";
72
+ context.context.logger.error(`An error occurred during ${hookSource} hook matcher execution:`, error);
73
+ throw new APIError("INTERNAL_SERVER_ERROR", { message: "An error occurred during hook matcher execution. Check the logs for more details." });
74
+ }
75
+ if (!matched) continue;
76
+ const hookSource = hooksSourceWeakMap.get(hook.handler) ?? "unknown";
77
+ const route = endpoint.path ?? "/:virtual";
78
+ const result = await withSpan(`hook before ${route} ${hookSource}`, {
79
+ [ATTR_HOOK_TYPE]: "before",
80
+ [ATTR_HTTP_ROUTE]: route,
81
+ [ATTR_CONTEXT]: hookSource,
82
+ [ATTR_OPERATION_ID]: operationId
83
+ }, () => hook.handler({
84
+ ...context,
85
+ returnHeaders: true
86
+ })).catch((e) => {
87
+ if (isAPIError(e) && shouldPublishLog(context.context.logger.level, "debug")) e.stack = e.errorStack;
88
+ throw e;
89
+ });
90
+ mergeResponseHeaders(context.context, result?.headers);
91
+ const hookReturn = result?.response;
92
+ if (hookReturn && typeof hookReturn === "object") {
93
+ if ("context" in hookReturn && typeof hookReturn.context === "object") {
94
+ const { headers, ...rest } = hookReturn.context;
95
+ if (headers instanceof Headers) if (modifiedContext.headers) headers.forEach((value, key) => {
96
+ modifiedContext.headers?.set(key, value);
97
+ });
98
+ else modifiedContext.headers = headers;
99
+ modifiedContext = defuReplaceArrays(rest, modifiedContext);
100
+ continue;
101
+ }
102
+ return hookReturn;
103
+ }
104
+ }
105
+ return { context: modifiedContext };
106
+ }
107
+ async function runAfterHooks(context, hooks, endpoint, operationId) {
108
+ for (const hook of hooks) {
109
+ if (!hook.matcher(context)) continue;
110
+ const hookSource = hooksSourceWeakMap.get(hook.handler) ?? "unknown";
111
+ const route = endpoint.path ?? "/:virtual";
112
+ const result = await withSpan(`hook after ${route} ${hookSource}`, {
113
+ [ATTR_HOOK_TYPE]: "after",
114
+ [ATTR_HTTP_ROUTE]: route,
115
+ [ATTR_CONTEXT]: hookSource,
116
+ [ATTR_OPERATION_ID]: operationId
117
+ }, () => hook.handler(context)).catch((e) => {
118
+ if (isAPIError(e)) {
119
+ if (shouldPublishLog(context.context.logger.level, "debug")) e.stack = e.errorStack;
120
+ return {
121
+ response: e,
122
+ headers: mergeAPIErrorHeaders(e)
123
+ };
124
+ }
125
+ throw e;
126
+ });
127
+ mergeResponseHeaders(context.context, result.headers);
128
+ if (result.response !== void 0) context.context.returned = result.response;
129
+ }
130
+ return {
131
+ response: context.context.returned,
132
+ headers: context.context.responseHeaders
133
+ };
134
+ }
135
+ function getHooks(authContext) {
136
+ const plugins = authContext.options.plugins || [];
137
+ const beforeHooks = [];
138
+ const afterHooks = [];
139
+ const beforeHookHandler = authContext.options.hooks?.before;
140
+ if (beforeHookHandler) {
141
+ hooksSourceWeakMap.set(beforeHookHandler, "user");
142
+ beforeHooks.push({
143
+ matcher: () => true,
144
+ handler: beforeHookHandler
145
+ });
146
+ }
147
+ const afterHookHandler = authContext.options.hooks?.after;
148
+ if (afterHookHandler) {
149
+ hooksSourceWeakMap.set(afterHookHandler, "user");
150
+ afterHooks.push({
151
+ matcher: () => true,
152
+ handler: afterHookHandler
153
+ });
154
+ }
155
+ const pluginBeforeHooks = plugins.flatMap((plugin) => (plugin.hooks?.before ?? []).map((h) => {
156
+ hooksSourceWeakMap.set(h.handler, `plugin:${plugin.id}`);
157
+ return h;
158
+ }));
159
+ const pluginAfterHooks = plugins.flatMap((plugin) => (plugin.hooks?.after ?? []).map((h) => {
160
+ hooksSourceWeakMap.set(h.handler, `plugin:${plugin.id}`);
161
+ return h;
162
+ }));
163
+ if (pluginBeforeHooks.length) beforeHooks.push(...pluginBeforeHooks);
164
+ if (pluginAfterHooks.length) afterHooks.push(...pluginAfterHooks);
165
+ return {
166
+ beforeHooks,
167
+ afterHooks
168
+ };
169
+ }
170
+ /**
171
+ * Run a single endpoint through the configured `hooks.before` / `hooks.after`
172
+ * pipeline, normalizing the response, headers, and `APIError`s the same way a
173
+ * router or `auth.api.*` dispatch does.
174
+ *
175
+ * This is the canonical hook runner. The HTTP router and `auth.api.*` reach it
176
+ * through {@link toAuthEndpoints}. Plugins call it directly when they need to
177
+ * re-enter the pipeline on purpose, such as resuming `/oauth2/authorize` after
178
+ * a fresh sign-in. Calling an endpoint as a plain function deliberately skips
179
+ * hooks; `dispatchAuthEndpoint` is the supported way to opt back in.
180
+ *
181
+ * @param endpoint The endpoint to dispatch.
182
+ * @param input Input context whose `context` is an already-resolved `AuthContext`.
183
+ */
184
+ async function dispatchAuthEndpoint(endpoint, input) {
185
+ const operationId = input.operationId ?? getOperationId(endpoint);
186
+ const route = endpoint.path ?? "/:virtual";
187
+ const endpointMethod = endpoint.options?.method;
188
+ const defaultMethod = Array.isArray(endpointMethod) ? endpointMethod[0] : endpointMethod;
189
+ const methodName = input.method ?? input.request?.method ?? defaultMethod ?? "?";
190
+ const shouldReturnResponse = input.asResponse ?? isRequestLike(input.request);
191
+ let internalContext = {
192
+ ...input,
193
+ context: {
194
+ ...input.context,
195
+ returned: void 0,
196
+ responseHeaders: void 0,
197
+ session: input.context.session ?? null
198
+ },
199
+ path: endpoint.path,
200
+ headers: input.headers ? new Headers(input.headers) : void 0
201
+ };
202
+ return withSpan(`${methodName} ${route}`, {
203
+ [ATTR_HTTP_ROUTE]: route,
204
+ [ATTR_OPERATION_ID]: operationId
205
+ }, async () => runWithEndpointContext(internalContext, async () => {
206
+ const { beforeHooks, afterHooks } = getHooks(internalContext.context);
207
+ const before = await runBeforeHooks(internalContext, beforeHooks, endpoint, operationId);
208
+ if ("context" in before && before.context && typeof before.context === "object") {
209
+ const { headers, ...rest } = before.context;
210
+ if (headers) {
211
+ if (!internalContext.headers) internalContext.headers = new Headers();
212
+ const requestHeaders = internalContext.headers;
213
+ headers.forEach((value, key) => {
214
+ requestHeaders.set(key, value);
215
+ });
216
+ }
217
+ internalContext = defuReplaceArrays(rest, internalContext);
218
+ } else if (before) {
219
+ const responseHeaders = internalContext.context.responseHeaders;
220
+ return shouldReturnResponse ? toResponse(before, { headers: responseHeaders }) : input.returnHeaders ? {
221
+ headers: responseHeaders,
222
+ response: before
223
+ } : before;
224
+ }
225
+ internalContext.asResponse = false;
226
+ internalContext.returnHeaders = true;
227
+ internalContext.returnStatus = true;
228
+ const result = await runWithEndpointContext(internalContext, () => withSpan(`handler ${route}`, {
229
+ [ATTR_HTTP_ROUTE]: route,
230
+ [ATTR_OPERATION_ID]: operationId
231
+ }, () => endpoint(internalContext))).catch((e) => {
232
+ if (isAPIError(e)) return {
233
+ response: e,
234
+ status: e.statusCode,
235
+ headers: mergeAPIErrorHeaders(e)
236
+ };
237
+ throw e;
238
+ });
239
+ if (result instanceof Response) return result;
240
+ internalContext.context.returned = result.response;
241
+ internalContext.context.responseHeaders = result.headers ?? void 0;
242
+ const after = await runAfterHooks(internalContext, afterHooks, endpoint, operationId);
243
+ if (after.response !== void 0) result.response = after.response;
244
+ result.headers = after.headers ?? result.headers;
245
+ if (isAPIError(result.response) && shouldPublishLog(internalContext.context.logger.level, "debug")) result.response.stack = result.response.errorStack;
246
+ if (isAPIError(result.response) && !shouldReturnResponse) {
247
+ if (result.headers) Object.defineProperty(result.response, kAPIErrorHeaderSymbol, {
248
+ enumerable: false,
249
+ configurable: true,
250
+ writable: false,
251
+ value: result.headers
252
+ });
253
+ throw result.response;
254
+ }
255
+ return shouldReturnResponse ? toResponse(result.response, {
256
+ headers: result.headers ?? void 0,
257
+ status: result.status
258
+ }) : input.returnHeaders ? input.returnStatus ? {
259
+ headers: result.headers,
260
+ response: result.response,
261
+ status: result.status
262
+ } : {
263
+ headers: result.headers,
264
+ response: result.response
265
+ } : input.returnStatus ? {
266
+ response: result.response,
267
+ status: result.status
268
+ } : result.response;
269
+ }));
270
+ }
271
+ //#endregion
272
+ export { dispatchAuthEndpoint, getOperationId };
@@ -2,6 +2,7 @@ import { OverrideMerge, Prettify as Prettify$1, UnionToIntersection } from "../t
2
2
  import { AdditionalSessionFieldsInput, AdditionalUserFieldsInput } from "../types/models.mjs";
3
3
  import { getIp } from "../utils/get-request-ip.mjs";
4
4
  import { isAPIError } from "../utils/is-api-error.mjs";
5
+ import { DispatchContext, dispatchAuthEndpoint } from "./dispatch.mjs";
5
6
  import { requireOrgRole, requireResourceOwnership } from "./middlewares/authorization.mjs";
6
7
  import { formCsrfMiddleware, originCheck, originCheckMiddleware } from "./middlewares/origin-check.mjs";
7
8
  import { accountInfo, getAccessToken, linkSocialAccount, listUserAccounts, refreshToken, unlinkAccount } from "./routes/account.mjs";
@@ -16,7 +17,7 @@ import { signOut } from "./routes/sign-out.mjs";
16
17
  import { signUpEmail } from "./routes/sign-up.mjs";
17
18
  import { updateSession } from "./routes/update-session.mjs";
18
19
  import { changeEmail, changePassword, deleteUser, deleteUserCallback, setPassword, updateUser } from "./routes/update-user.mjs";
19
- import { getOAuthState } from "./state/oauth.mjs";
20
+ import { addOAuthServerContext, getOAuthState } from "./state/oauth.mjs";
20
21
  import { getShouldSkipSessionRefresh, setShouldSkipSessionRefresh } from "./state/should-session-refresh.mjs";
21
22
  import { AuthContext, Awaitable, BetterAuthOptions, BetterAuthPlugin } from "@better-auth/core";
22
23
  import * as _better_auth_core_db0 from "@better-auth/core/db";
@@ -99,6 +100,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
99
100
  accessToken: zod.ZodOptional<zod.ZodString>;
100
101
  refreshToken: zod.ZodOptional<zod.ZodString>;
101
102
  expiresAt: zod.ZodOptional<zod.ZodNumber>;
103
+ scopes: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
102
104
  user: zod.ZodOptional<zod.ZodObject<{
103
105
  name: zod.ZodOptional<zod.ZodObject<{
104
106
  firstName: zod.ZodOptional<zod.ZodString>;
@@ -127,6 +129,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
127
129
  accessToken: zod.ZodOptional<zod.ZodString>;
128
130
  refreshToken: zod.ZodOptional<zod.ZodString>;
129
131
  expiresAt: zod.ZodOptional<zod.ZodNumber>;
132
+ scopes: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
130
133
  user: zod.ZodOptional<zod.ZodObject<{
131
134
  name: zod.ZodOptional<zod.ZodObject<{
132
135
  firstName: zod.ZodOptional<zod.ZodString>;
@@ -1709,7 +1712,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1709
1712
  userId: {
1710
1713
  type: string;
1711
1714
  };
1712
- scopes: {
1715
+ grantedScopes: {
1713
1716
  type: string;
1714
1717
  items: {
1715
1718
  type: string;
@@ -1726,7 +1729,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1726
1729
  };
1727
1730
  };
1728
1731
  }, {
1729
- scopes: string[];
1732
+ grantedScopes: string[];
1730
1733
  id: string;
1731
1734
  createdAt: Date;
1732
1735
  updatedAt: Date;
@@ -1866,6 +1869,12 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1866
1869
  type: string;
1867
1870
  format: string;
1868
1871
  };
1872
+ grantedScopes: {
1873
+ type: string;
1874
+ items: {
1875
+ type: string;
1876
+ };
1877
+ };
1869
1878
  };
1870
1879
  };
1871
1880
  };
@@ -1882,7 +1891,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1882
1891
  refreshToken: string;
1883
1892
  accessTokenExpiresAt: Date | undefined;
1884
1893
  refreshTokenExpiresAt: Date | null | undefined;
1885
- scope: string | null | undefined;
1894
+ grantedScopes: string[];
1886
1895
  idToken: string | null | undefined;
1887
1896
  providerId: string;
1888
1897
  accountId: string;
@@ -1932,7 +1941,7 @@ declare function getEndpoints<Option extends BetterAuthOptions>(ctx: Awaitable<A
1932
1941
  }, {
1933
1942
  accessToken: string;
1934
1943
  accessTokenExpiresAt: Date | undefined;
1935
- scopes: string[];
1944
+ grantedScopes: string[];
1936
1945
  idToken: string | undefined;
1937
1946
  }>;
1938
1947
  readonly accountInfo: better_call0.StrictEndpoint<"/account-info", {
@@ -2075,6 +2084,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
2075
2084
  accessToken: zod.ZodOptional<zod.ZodString>;
2076
2085
  refreshToken: zod.ZodOptional<zod.ZodString>;
2077
2086
  expiresAt: zod.ZodOptional<zod.ZodNumber>;
2087
+ scopes: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
2078
2088
  user: zod.ZodOptional<zod.ZodObject<{
2079
2089
  name: zod.ZodOptional<zod.ZodObject<{
2080
2090
  firstName: zod.ZodOptional<zod.ZodString>;
@@ -2103,6 +2113,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
2103
2113
  accessToken: zod.ZodOptional<zod.ZodString>;
2104
2114
  refreshToken: zod.ZodOptional<zod.ZodString>;
2105
2115
  expiresAt: zod.ZodOptional<zod.ZodNumber>;
2116
+ scopes: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
2106
2117
  user: zod.ZodOptional<zod.ZodObject<{
2107
2118
  name: zod.ZodOptional<zod.ZodObject<{
2108
2119
  firstName: zod.ZodOptional<zod.ZodString>;
@@ -3685,7 +3696,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3685
3696
  userId: {
3686
3697
  type: string;
3687
3698
  };
3688
- scopes: {
3699
+ grantedScopes: {
3689
3700
  type: string;
3690
3701
  items: {
3691
3702
  type: string;
@@ -3702,7 +3713,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3702
3713
  };
3703
3714
  };
3704
3715
  }, {
3705
- scopes: string[];
3716
+ grantedScopes: string[];
3706
3717
  id: string;
3707
3718
  createdAt: Date;
3708
3719
  updatedAt: Date;
@@ -3842,6 +3853,12 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3842
3853
  type: string;
3843
3854
  format: string;
3844
3855
  };
3856
+ grantedScopes: {
3857
+ type: string;
3858
+ items: {
3859
+ type: string;
3860
+ };
3861
+ };
3845
3862
  };
3846
3863
  };
3847
3864
  };
@@ -3858,7 +3875,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3858
3875
  refreshToken: string;
3859
3876
  accessTokenExpiresAt: Date | undefined;
3860
3877
  refreshTokenExpiresAt: Date | null | undefined;
3861
- scope: string | null | undefined;
3878
+ grantedScopes: string[];
3862
3879
  idToken: string | null | undefined;
3863
3880
  providerId: string;
3864
3881
  accountId: string;
@@ -3908,7 +3925,7 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3908
3925
  }, {
3909
3926
  accessToken: string;
3910
3927
  accessTokenExpiresAt: Date | undefined;
3911
- scopes: string[];
3928
+ grantedScopes: string[];
3912
3929
  idToken: string | undefined;
3913
3930
  }>;
3914
3931
  readonly accountInfo: better_call0.StrictEndpoint<"/account-info", {
@@ -3972,4 +3989,4 @@ declare const router: <Option extends BetterAuthOptions>(ctx: AuthContext, optio
3972
3989
  } extends infer T_2 ? { [K in keyof T_2 as K extends keyof T_1 ? never : K]: T_2[K] } : never) & T_1> : never : never : never;
3973
3990
  };
3974
3991
  //#endregion
3975
- export { APIError, type AuthEndpoint, type AuthMiddleware, accountInfo, callbackOAuth, changeEmail, changePassword, checkEndpointConflicts, createAuthEndpoint, createAuthMiddleware, createEmailVerificationToken, deleteUser, deleteUserCallback, error, formCsrfMiddleware, freshSessionMiddleware, getAccessToken, getEndpoints, getIp, getOAuthState, getSession, getSessionFromCtx, getShouldSkipSessionRefresh, isAPIError, linkSocialAccount, listSessions, listUserAccounts, ok, optionsMiddleware, originCheck, originCheckMiddleware, refreshToken, requestOnlySessionMiddleware, requestPasswordReset, requestPasswordResetCallback, requireOrgRole, requireResourceOwnership, resetPassword, revokeOtherSessions, revokeSession, revokeSessions, router, sendVerificationEmail, sendVerificationEmailFn, sensitiveSessionMiddleware, sessionMiddleware, setPassword, setShouldSkipSessionRefresh, signInEmail, signInSocial, signOut, signUpEmail, unlinkAccount, updateSession, updateUser, verifyEmail, verifyPassword };
3992
+ export { APIError, type AuthEndpoint, type AuthMiddleware, type DispatchContext, accountInfo, addOAuthServerContext, callbackOAuth, changeEmail, changePassword, checkEndpointConflicts, createAuthEndpoint, createAuthMiddleware, createEmailVerificationToken, deleteUser, deleteUserCallback, dispatchAuthEndpoint, error, formCsrfMiddleware, freshSessionMiddleware, getAccessToken, getEndpoints, getIp, getOAuthState, getSession, getSessionFromCtx, getShouldSkipSessionRefresh, isAPIError, linkSocialAccount, listSessions, listUserAccounts, ok, optionsMiddleware, originCheck, originCheckMiddleware, refreshToken, requestOnlySessionMiddleware, requestPasswordReset, requestPasswordResetCallback, requireOrgRole, requireResourceOwnership, resetPassword, revokeOtherSessions, revokeSession, revokeSessions, router, sendVerificationEmail, sendVerificationEmailFn, sensitiveSessionMiddleware, sessionMiddleware, setPassword, setShouldSkipSessionRefresh, signInEmail, signInSocial, signOut, signUpEmail, unlinkAccount, updateSession, updateUser, verifyEmail, verifyPassword };
@@ -3,7 +3,7 @@ import { requireOrgRole, requireResourceOwnership } from "./middlewares/authoriz
3
3
  import { formCsrfMiddleware, originCheck, originCheckMiddleware } from "./middlewares/origin-check.mjs";
4
4
  import { getIp } from "../utils/get-request-ip.mjs";
5
5
  import { onRequestRateLimit, onResponseRateLimit } from "./rate-limiter/index.mjs";
6
- import { getOAuthState } from "./state/oauth.mjs";
6
+ import { addOAuthServerContext, getOAuthState } from "./state/oauth.mjs";
7
7
  import { getShouldSkipSessionRefresh, setShouldSkipSessionRefresh } from "./state/should-session-refresh.mjs";
8
8
  import { freshSessionMiddleware, getSession, getSessionFromCtx, listSessions, requestOnlySessionMiddleware, revokeOtherSessions, revokeSession, revokeSessions, sensitiveSessionMiddleware, sessionMiddleware } from "./routes/session.mjs";
9
9
  import { accountInfo, getAccessToken, linkSocialAccount, listUserAccounts, refreshToken, unlinkAccount } from "./routes/account.mjs";
@@ -17,6 +17,7 @@ import { signOut } from "./routes/sign-out.mjs";
17
17
  import { signUpEmail } from "./routes/sign-up.mjs";
18
18
  import { updateSession } from "./routes/update-session.mjs";
19
19
  import { changeEmail, changePassword, deleteUser, deleteUserCallback, setPassword, updateUser } from "./routes/update-user.mjs";
20
+ import { dispatchAuthEndpoint } from "./dispatch.mjs";
20
21
  import { toAuthEndpoints } from "./to-auth-endpoints.mjs";
21
22
  import { logger } from "@better-auth/core/env";
22
23
  import { APIError } from "@better-auth/core/error";
@@ -213,4 +214,4 @@ const router = (ctx, options) => {
213
214
  });
214
215
  };
215
216
  //#endregion
216
- export { APIError, accountInfo, callbackOAuth, changeEmail, changePassword, checkEndpointConflicts, createAuthEndpoint, createAuthMiddleware, createEmailVerificationToken, deleteUser, deleteUserCallback, error, formCsrfMiddleware, freshSessionMiddleware, getAccessToken, getEndpoints, getIp, getOAuthState, getSession, getSessionFromCtx, getShouldSkipSessionRefresh, isAPIError, linkSocialAccount, listSessions, listUserAccounts, ok, optionsMiddleware, originCheck, originCheckMiddleware, refreshToken, requestOnlySessionMiddleware, requestPasswordReset, requestPasswordResetCallback, requireOrgRole, requireResourceOwnership, resetPassword, revokeOtherSessions, revokeSession, revokeSessions, router, sendVerificationEmail, sendVerificationEmailFn, sensitiveSessionMiddleware, sessionMiddleware, setPassword, setShouldSkipSessionRefresh, signInEmail, signInSocial, signOut, signUpEmail, unlinkAccount, updateSession, updateUser, verifyEmail, verifyPassword };
217
+ export { APIError, accountInfo, addOAuthServerContext, callbackOAuth, changeEmail, changePassword, checkEndpointConflicts, createAuthEndpoint, createAuthMiddleware, createEmailVerificationToken, deleteUser, deleteUserCallback, dispatchAuthEndpoint, error, formCsrfMiddleware, freshSessionMiddleware, getAccessToken, getEndpoints, getIp, getOAuthState, getSession, getSessionFromCtx, getShouldSkipSessionRefresh, isAPIError, linkSocialAccount, listSessions, listUserAccounts, ok, optionsMiddleware, originCheck, originCheckMiddleware, refreshToken, requestOnlySessionMiddleware, requestPasswordReset, requestPasswordResetCallback, requireOrgRole, requireResourceOwnership, resetPassword, revokeOtherSessions, revokeSession, revokeSessions, router, sendVerificationEmail, sendVerificationEmailFn, sensitiveSessionMiddleware, sessionMiddleware, setPassword, setShouldSkipSessionRefresh, signInEmail, signInSocial, signOut, signUpEmail, unlinkAccount, updateSession, updateUser, verifyEmail, verifyPassword };
@@ -141,6 +141,7 @@ async function validateFormCsrf(ctx) {
141
141
  }
142
142
  return await validateOrigin(ctx, true);
143
143
  }
144
+ if (headers.get("origin") || headers.get("referer")) return await validateOrigin(ctx, true);
144
145
  }
145
146
  //#endregion
146
147
  export { formCsrfMiddleware, originCheck, originCheckMiddleware };
@@ -62,7 +62,7 @@ declare const listUserAccounts: better_call0.StrictEndpoint<"/list-accounts", {
62
62
  userId: {
63
63
  type: string;
64
64
  };
65
- scopes: {
65
+ grantedScopes: {
66
66
  type: string;
67
67
  items: {
68
68
  type: string;
@@ -79,7 +79,7 @@ declare const listUserAccounts: better_call0.StrictEndpoint<"/list-accounts", {
79
79
  };
80
80
  };
81
81
  }, {
82
- scopes: string[];
82
+ grantedScopes: string[];
83
83
  id: string;
84
84
  createdAt: Date;
85
85
  updatedAt: Date;
@@ -266,7 +266,7 @@ declare const getAccessToken: better_call0.StrictEndpoint<"/get-access-token", {
266
266
  }, {
267
267
  accessToken: string;
268
268
  accessTokenExpiresAt: Date | undefined;
269
- scopes: string[];
269
+ grantedScopes: string[];
270
270
  idToken: string | undefined;
271
271
  }>;
272
272
  declare const refreshToken: better_call0.StrictEndpoint<"/refresh-token", {
@@ -307,6 +307,12 @@ declare const refreshToken: better_call0.StrictEndpoint<"/refresh-token", {
307
307
  type: string;
308
308
  format: string;
309
309
  };
310
+ grantedScopes: {
311
+ type: string;
312
+ items: {
313
+ type: string;
314
+ };
315
+ };
310
316
  };
311
317
  };
312
318
  };
@@ -323,7 +329,7 @@ declare const refreshToken: better_call0.StrictEndpoint<"/refresh-token", {
323
329
  refreshToken: string;
324
330
  accessTokenExpiresAt: Date | undefined;
325
331
  refreshTokenExpiresAt: Date | null | undefined;
326
- scope: string | null | undefined;
332
+ grantedScopes: string[];
327
333
  idToken: string | null | undefined;
328
334
  providerId: string;
329
335
  accountId: string;