better-auth 0.3.5-beta.7 → 0.3.5-beta.8

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.
@@ -1,4 +1,4 @@
1
- import { A as Adapter } from '../index-hN0bCS_b.js';
1
+ import { A as Adapter } from '../index-Bkb3x6r0.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import '../index-QaO4zgiz.js';
@@ -1,5 +1,5 @@
1
1
  import { Db } from 'mongodb';
2
- import { W as Where } from '../index-hN0bCS_b.js';
2
+ import { W as Where } from '../index-Bkb3x6r0.js';
3
3
  import 'zod';
4
4
  import 'kysely';
5
5
  import '../index-QaO4zgiz.js';
@@ -1,4 +1,4 @@
1
- import { A as Adapter } from '../index-hN0bCS_b.js';
1
+ import { A as Adapter } from '../index-Bkb3x6r0.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import '../index-QaO4zgiz.js';
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { e as AuthEndpoint, f as AuthMiddleware, v as callbackOAuth, T as changePassword, d as createAuthEndpoint, c as createAuthMiddleware, M as createEmailVerificationToken, $ as csrfMiddleware, V as deleteUser, Y as error, J as forgetPassword, K as forgetPasswordCallback, X as getCSRFToken, r as getEndpoints, w as getSession, x as getSessionFromCtx, z as listSessions, Z as ok, o as optionsMiddleware, L as resetPassword, C as revokeSession, D as revokeSessions, s as router, N as sendVerificationEmail, y as sessionMiddleware, U as setPassword, u as signInEmail, t as signInOAuth, E as signOut, _ as signUpEmail, Q as updateUser, O as verifyEmail } from './index-hN0bCS_b.js';
1
+ export { e as AuthEndpoint, f as AuthMiddleware, v as callbackOAuth, T as changePassword, d as createAuthEndpoint, c as createAuthMiddleware, M as createEmailVerificationToken, $ as csrfMiddleware, V as deleteUser, Y as error, J as forgetPassword, K as forgetPasswordCallback, X as getCSRFToken, r as getEndpoints, w as getSession, x as getSessionFromCtx, z as listSessions, Z as ok, o as optionsMiddleware, L as resetPassword, C as revokeSession, D as revokeSessions, s as router, N as sendVerificationEmail, y as sessionMiddleware, U as setPassword, u as signInEmail, t as signInOAuth, E as signOut, _ as signUpEmail, Q as updateUser, O as verifyEmail } from './index-Bkb3x6r0.js';
2
2
  import './helper-DPDj8Nix.js';
3
3
  import 'zod';
4
4
  export { APIError } from 'better-call';
package/dist/api.js CHANGED
@@ -68,6 +68,11 @@ var csrfMiddleware = createAuthMiddleware(
68
68
  return;
69
69
  }
70
70
  const csrfToken = ctx.body?.csrfToken;
71
+ if (!csrfToken) {
72
+ throw new APIError("UNAUTHORIZED", {
73
+ message: "CSRF Token is required"
74
+ });
75
+ }
71
76
  const csrfCookie = await ctx.getSignedCookie(
72
77
  ctx.context.authCookies.csrfToken.name,
73
78
  ctx.context.secret
@@ -804,7 +809,7 @@ var getDate = (span, unit = "ms") => {
804
809
  return new Date(date.getTime() + (unit === "sec" ? span * 1e3 : span));
805
810
  };
806
811
 
807
- // src/utils/cookies.ts
812
+ // src/cookies/index.ts
808
813
  import { TimeSpan } from "oslo";
809
814
  async function setSessionCookie(ctx, sessionToken, dontRememberMe, overrides) {
810
815
  const options = ctx.context.authCookies.sessionToken.options;
@@ -2,10 +2,10 @@ import * as nanostores from 'nanostores';
2
2
  import { A as AccessControl, S as StatementsPrimitive, R as Role } from '../statement-CfnyN34h.js';
3
3
  import * as _better_fetch_fetch from '@better-fetch/fetch';
4
4
  import { BetterFetchOption } from '@better-fetch/fetch';
5
- import { o as organization, f as Organization, M as Member, I as Invitation, u as username, m as magicLink, d as phoneNumber, e as anonymous } from '../index-BZV4xXJh.js';
6
- export { g as getPasskeyActions, c as passkeyClient, a as twoFactorClient } from '../index-BZV4xXJh.js';
5
+ import { o as organization, f as Organization, M as Member, I as Invitation, u as username, m as magicLink, d as phoneNumber, e as anonymous } from '../index-JGsMiE1o.js';
6
+ export { g as getPasskeyActions, c as passkeyClient, a as twoFactorClient } from '../index-JGsMiE1o.js';
7
7
  import { P as Prettify } from '../helper-DPDj8Nix.js';
8
- import { F as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../index-hN0bCS_b.js';
8
+ import { F as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../index-Bkb3x6r0.js';
9
9
  import '../index-QaO4zgiz.js';
10
10
  import 'arctic';
11
11
  import 'zod';
package/dist/client.d.ts CHANGED
@@ -6,7 +6,7 @@ import { BetterFetch, BetterFetchError, BetterFetchOption } from '@better-fetch/
6
6
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
7
7
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, InferSessionFromClient, InferUserFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
8
8
  export { AtomListener, InferPluginsFromClient } from './types.js';
9
- import './index-hN0bCS_b.js';
9
+ import './index-Bkb3x6r0.js';
10
10
  import 'kysely';
11
11
  import './index-QaO4zgiz.js';
12
12
  import 'arctic';
package/dist/client.js CHANGED
@@ -78,7 +78,6 @@ var addCurrentURL = {
78
78
  }
79
79
  }
80
80
  };
81
- var cache = /* @__PURE__ */ new Map();
82
81
  var csrfPlugin = {
83
82
  id: "csrf",
84
83
  name: "CSRF Check",
@@ -90,39 +89,36 @@ var csrfPlugin = {
90
89
  }
91
90
  if (options?.method !== "GET") {
92
91
  options = options || {};
93
- const csrfToken = cache.get("CSRF_TOKEN");
94
- if (!csrfToken) {
95
- const { data, error } = await betterFetch("/csrf", {
96
- body: void 0,
97
- baseURL: options.baseURL,
98
- plugins: [],
99
- method: "GET",
100
- credentials: "include",
101
- customFetchImpl: options.customFetchImpl
102
- });
103
- if (error) {
104
- if (error.status === 404) {
105
- throw new BetterAuthError(
106
- "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
107
- );
108
- }
109
- if (error.status === 429) {
110
- return new Response(
111
- JSON.stringify({
112
- message: "Too many requests. Please try again later."
113
- }),
114
- {
115
- status: 429,
116
- statusText: "Too Many Requests"
117
- }
118
- );
119
- }
92
+ const { data, error } = await betterFetch("/csrf", {
93
+ body: void 0,
94
+ baseURL: options.baseURL,
95
+ plugins: [],
96
+ method: "GET",
97
+ credentials: "include",
98
+ customFetchImpl: options.customFetchImpl
99
+ });
100
+ if (error) {
101
+ if (error.status === 404) {
120
102
  throw new BetterAuthError(
121
- "Failed to fetch CSRF token: " + error.message
103
+ "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
104
+ );
105
+ }
106
+ if (error.status === 429) {
107
+ return new Response(
108
+ JSON.stringify({
109
+ message: "Too many requests. Please try again later."
110
+ }),
111
+ {
112
+ status: 429,
113
+ statusText: "Too Many Requests"
114
+ }
122
115
  );
123
116
  }
124
- cache.set("CSRF_TOKEN", data.csrfToken);
117
+ throw new BetterAuthError(
118
+ "Failed to fetch CSRF token: " + error.message
119
+ );
125
120
  }
121
+ const csrfToken = data?.csrfToken;
126
122
  options.body = {
127
123
  ...options?.body,
128
124
  csrfToken
@@ -141,7 +137,7 @@ var getClientConfig = (options) => {
141
137
  method: "GET",
142
138
  ...options?.fetchOptions,
143
139
  plugins: [
144
- csrfPlugin,
140
+ ...!options?.disableCSRFTokenCheck ? [csrfPlugin] : [],
145
141
  redirectPlugin,
146
142
  addCurrentURL,
147
143
  ...options?.fetchOptions?.plugins?.filter((pl) => pl !== void 0) || [],
@@ -70,8 +70,9 @@ declare function getCookies(options: BetterAuthOptions): {
70
70
  sessionToken: {
71
71
  name: string;
72
72
  options: {
73
+ domain?: string | undefined;
73
74
  httpOnly: true;
74
- sameSite: "lax";
75
+ sameSite: "none" | "lax";
75
76
  path: string;
76
77
  secure: boolean;
77
78
  maxAge: number;
@@ -80,8 +81,9 @@ declare function getCookies(options: BetterAuthOptions): {
80
81
  csrfToken: {
81
82
  name: string;
82
83
  options: {
84
+ domain?: string | undefined;
83
85
  httpOnly: true;
84
- sameSite: "lax";
86
+ sameSite: "none" | "lax";
85
87
  path: string;
86
88
  secure: boolean;
87
89
  maxAge: number;
@@ -90,8 +92,9 @@ declare function getCookies(options: BetterAuthOptions): {
90
92
  state: {
91
93
  name: string;
92
94
  options: {
95
+ domain?: string | undefined;
93
96
  httpOnly: true;
94
- sameSite: "lax";
97
+ sameSite: "none" | "lax";
95
98
  path: string;
96
99
  secure: boolean;
97
100
  maxAge: number;
@@ -110,7 +113,7 @@ declare function getCookies(options: BetterAuthOptions): {
110
113
  options: CookieOptions;
111
114
  };
112
115
  };
113
- declare function createCookieGetter(options: BetterAuthOptions): (cookieName: string, options?: CookieOptions) => {
116
+ declare function createCookieGetter(options: BetterAuthOptions): (cookieName: string, opts?: CookieOptions) => {
114
117
  name: string;
115
118
  options: CookieOptions;
116
119
  };
@@ -737,8 +740,6 @@ type MysqlPool = Pool;
737
740
 
738
741
  type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql";
739
742
 
740
- type EligibleCookies = keyof BetterAuthCookies;
741
-
742
743
  type AdditionalUserFieldsInput<Options extends BetterAuthOptions> = InferFieldsFromOptions<Options, "user", "input">;
743
744
  type AdditionalUserFieldsOutput<Options extends BetterAuthOptions> = InferFieldsFromPlugins<Options, "user"> & InferFieldsFromOptions<Options, "user">;
744
745
  type AdditionalSessionFieldsInput<Options extends BetterAuthOptions> = InferFieldsFromPlugins<Options, "session", "input"> & InferFieldsFromOptions<Options, "session", "input">;
@@ -1055,12 +1056,9 @@ interface BetterAuthOptions {
1055
1056
  */
1056
1057
  enabled: boolean;
1057
1058
  /**
1058
- * List of cookies that should be shared across subdomains
1059
- *
1060
- * by default, only sessionToken, csrfToken and dontRememberToken
1061
- * cookies will be shared across subdomains
1059
+ * Additional cookies to be shared across subdomains
1062
1060
  */
1063
- eligibleCookies?: EligibleCookies[];
1061
+ additionalCookies?: string[];
1064
1062
  /**
1065
1063
  * The domain to use for the cookies
1066
1064
  *
@@ -5,7 +5,7 @@ import { P as Prettify } from './helper-DPDj8Nix.js';
5
5
  import { A as AccessControl, R as Role, S as StatementsPrimitive, g as defaultRoles } from './statement-CfnyN34h.js';
6
6
  import * as _better_fetch_fetch from '@better-fetch/fetch';
7
7
  import { BetterFetch, BetterFetchOption } from '@better-fetch/fetch';
8
- import { H as HookEndpointContext } from './index-hN0bCS_b.js';
8
+ import { H as HookEndpointContext } from './index-Bkb3x6r0.js';
9
9
  import * as nanostores from 'nanostores';
10
10
  import { atom } from 'nanostores';
11
11
  import * as _simplewebauthn_types from '@simplewebauthn/types';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { a as Auth, a0 as betterAuth } from './index-hN0bCS_b.js';
1
+ export { a as Auth, a0 as betterAuth } from './index-Bkb3x6r0.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import './index-QaO4zgiz.js';
package/dist/index.js CHANGED
@@ -68,6 +68,11 @@ var csrfMiddleware = createAuthMiddleware(
68
68
  return;
69
69
  }
70
70
  const csrfToken = ctx.body?.csrfToken;
71
+ if (!csrfToken) {
72
+ throw new APIError("UNAUTHORIZED", {
73
+ message: "CSRF Token is required"
74
+ });
75
+ }
71
76
  const csrfCookie = await ctx.getSignedCookie(
72
77
  ctx.context.authCookies.csrfToken.name,
73
78
  ctx.context.secret
@@ -804,75 +809,89 @@ var getDate = (span, unit = "ms") => {
804
809
  return new Date(date.getTime() + (unit === "sec" ? span * 1e3 : span));
805
810
  };
806
811
 
807
- // src/utils/cookies.ts
812
+ // src/cookies/index.ts
808
813
  import { TimeSpan } from "oslo";
809
814
  function getCookies(options) {
810
815
  const secure = options.advanced?.useSecureCookies !== void 0 ? options.advanced?.useSecureCookies : options.baseURL?.startsWith("https://") || process.env.NODE_ENV === "production";
811
816
  const secureCookiePrefix = secure ? "__Secure-" : "";
812
817
  const cookiePrefix = "better-auth";
813
818
  const sessionMaxAge = new TimeSpan(7, "d").seconds();
819
+ const crossSubdomainEnabled = options.advanced?.crossSubDomainCookies?.enabled;
820
+ const domain = crossSubdomainEnabled ? options.advanced?.crossSubDomainCookies?.domain || (options.baseURL ? new URL(options.baseURL).hostname : void 0) : void 0;
821
+ if (crossSubdomainEnabled && !domain) {
822
+ throw new BetterAuthError(
823
+ "baseURL is required when crossSubdomainCookies are enabled"
824
+ );
825
+ }
826
+ const sameSite = crossSubdomainEnabled ? "none" : "lax";
814
827
  return {
815
828
  sessionToken: {
816
829
  name: `${secureCookiePrefix}${cookiePrefix}.session_token`,
817
830
  options: {
818
831
  httpOnly: true,
819
- sameSite: "lax",
832
+ sameSite,
820
833
  path: "/",
821
834
  secure: !!secureCookiePrefix,
822
- maxAge: sessionMaxAge
835
+ maxAge: sessionMaxAge,
836
+ ...crossSubdomainEnabled && { domain }
823
837
  }
824
838
  },
825
839
  csrfToken: {
826
- name: `${secureCookiePrefix ? "__Host-" : ""}${cookiePrefix}.csrf_token`,
840
+ name: `${secureCookiePrefix}${cookiePrefix}.csrf_token`,
827
841
  options: {
828
842
  httpOnly: true,
829
- sameSite: "lax",
843
+ sameSite,
830
844
  path: "/",
831
845
  secure: !!secureCookiePrefix,
832
- maxAge: 60 * 60 * 24 * 7
846
+ maxAge: 60 * 60 * 24 * 7,
847
+ ...crossSubdomainEnabled && { domain }
833
848
  }
834
849
  },
835
850
  state: {
836
851
  name: `${secureCookiePrefix}${cookiePrefix}.state`,
837
852
  options: {
838
853
  httpOnly: true,
839
- sameSite: "lax",
854
+ sameSite,
840
855
  path: "/",
841
856
  secure: !!secureCookiePrefix,
842
- maxAge: 60 * 15
857
+ maxAge: 60 * 15,
843
858
  // 15 minutes in seconds
859
+ ...crossSubdomainEnabled && { domain }
844
860
  }
845
861
  },
846
862
  pkCodeVerifier: {
847
863
  name: `${secureCookiePrefix}${cookiePrefix}.pk_code_verifier`,
848
864
  options: {
849
865
  httpOnly: true,
850
- sameSite: "lax",
866
+ sameSite,
851
867
  path: "/",
852
868
  secure: !!secureCookiePrefix,
853
- maxAge: 60 * 15
869
+ maxAge: 60 * 15,
854
870
  // 15 minutes in seconds
871
+ ...crossSubdomainEnabled && { domain }
855
872
  }
856
873
  },
857
874
  dontRememberToken: {
858
875
  name: `${secureCookiePrefix}${cookiePrefix}.dont_remember`,
859
876
  options: {
860
877
  httpOnly: true,
861
- sameSite: "lax",
878
+ sameSite,
862
879
  path: "/",
863
- secure: !!secureCookiePrefix
880
+ secure: !!secureCookiePrefix,
864
881
  //no max age so it expires when the browser closes
882
+ ...crossSubdomainEnabled && { domain }
865
883
  }
866
884
  },
867
885
  nonce: {
868
886
  name: `${secureCookiePrefix}${cookiePrefix}.nonce`,
869
887
  options: {
870
888
  httpOnly: true,
871
- sameSite: "lax",
889
+ sameSite,
872
890
  path: "/",
873
891
  secure: !!secureCookiePrefix,
874
- maxAge: 60 * 15
892
+ maxAge: 60 * 15,
875
893
  // 15 minutes in seconds
894
+ ...crossSubdomainEnabled && { domain }
876
895
  }
877
896
  }
878
897
  };
@@ -881,7 +900,11 @@ function createCookieGetter(options) {
881
900
  const secure = !!options.advanced?.useSecureCookies || process.env.NODE_ENV === "production";
882
901
  const secureCookiePrefix = secure ? "__Secure-" : "";
883
902
  const cookiePrefix = "better-auth";
884
- function getCookie(cookieName, options2) {
903
+ const domain = options.advanced?.crossSubDomainCookies?.domain || (options.baseURL ? new URL(options.baseURL).hostname : void 0);
904
+ function getCookie(cookieName, opts) {
905
+ const crossSubdomainEnabled = options.advanced?.crossSubDomainCookies?.enabled ? options.advanced.crossSubDomainCookies.additionalCookies?.includes(
906
+ cookieName
907
+ ) : void 0;
885
908
  return {
886
909
  name: process.env.NODE_ENV === "production" ? `${secureCookiePrefix}${cookiePrefix}.${cookieName}` : `${cookiePrefix}.${cookieName}`,
887
910
  options: {
@@ -890,7 +913,8 @@ function createCookieGetter(options) {
890
913
  path: "/",
891
914
  maxAge: 60 * 15,
892
915
  // 15 minutes in seconds
893
- ...options2
916
+ ...opts,
917
+ ...crossSubdomainEnabled && { domain }
894
918
  }
895
919
  };
896
920
  }
@@ -3926,63 +3950,6 @@ import { defu } from "defu";
3926
3950
  // src/utils/constants.ts
3927
3951
  var DEFAULT_SECRET = "better-auth-secret-123456789";
3928
3952
 
3929
- // src/internal-plugins/cross-subdomain/index.ts
3930
- function getEligibleCookies(authCookies, eligibleCookies) {
3931
- const cookies = [];
3932
- for (const cookie of eligibleCookies || []) {
3933
- cookies.push(authCookies[cookie].name);
3934
- }
3935
- return cookies;
3936
- }
3937
- var crossSubdomainCookies = (options) => {
3938
- return {
3939
- id: "cross-subdomain-cookies",
3940
- async onResponse(response, ctx) {
3941
- const setCookie = response.headers.get("set-cookie");
3942
- if (!setCookie) return { response };
3943
- const baseURL = ctx.baseURL;
3944
- const domain = options?.domain || new URL(baseURL).hostname;
3945
- const authCookies = ctx.authCookies;
3946
- const eligibleCookies = options?.eligibleCookies ? getEligibleCookies(
3947
- authCookies,
3948
- options.eligibleCookies
3949
- ) : [
3950
- authCookies.sessionToken.name,
3951
- authCookies.csrfToken.name,
3952
- authCookies.dontRememberToken.name
3953
- ];
3954
- const updatedCookies = setCookie.split(",").map((cookie) => {
3955
- let [name] = cookie.trim().split("=");
3956
- if (!eligibleCookies.includes(name)) return cookie;
3957
- name = name.replace("__Host-", "");
3958
- const parts = cookie.split(";").map((part) => part.trim());
3959
- const domainIndex = parts.findIndex(
3960
- (part) => part.toLowerCase().startsWith("domain=")
3961
- );
3962
- if (domainIndex !== -1) {
3963
- parts[domainIndex] = `Domain=${domain}`;
3964
- } else {
3965
- parts.push(`Domain=${domain}`);
3966
- }
3967
- const sameSiteIndex = parts.findIndex(
3968
- (part) => part.toLowerCase().startsWith("samesite=")
3969
- );
3970
- if (sameSiteIndex !== -1) {
3971
- parts[sameSiteIndex] = "SameSite=None";
3972
- } else {
3973
- parts.push("SameSite=None");
3974
- }
3975
- if (!parts.includes("Secure")) {
3976
- parts.push("Secure");
3977
- }
3978
- return parts.join("; ");
3979
- }).join(", ");
3980
- response.headers.set("set-cookie", updatedCookies);
3981
- return { response };
3982
- }
3983
- };
3984
- };
3985
-
3986
3953
  // src/init.ts
3987
3954
  var init = async (opts) => {
3988
3955
  let { options, context, dbHooks } = runPluginInit(opts);
@@ -3991,6 +3958,9 @@ var init = async (opts) => {
3991
3958
  const adapter = await getAdapter(options);
3992
3959
  const { kysely: db } = await createKyselyAdapter(options);
3993
3960
  const baseURL = getBaseURL(options.baseURL, options.basePath) || "";
3961
+ if (baseURL) {
3962
+ options.trustedOrigins = [...options.trustedOrigins || [], baseURL];
3963
+ }
3994
3964
  const secret = options.secret || process.env.BETTER_AUTH_SECRET || process.env.AUTH_SECRET || DEFAULT_SECRET;
3995
3965
  options = {
3996
3966
  ...options,
@@ -4085,12 +4055,6 @@ function runPluginInit(options) {
4085
4055
  function getInternalPlugins(options) {
4086
4056
  const plugins = [];
4087
4057
  if (options.advanced?.crossSubDomainCookies?.enabled) {
4088
- plugins.push(
4089
- crossSubdomainCookies({
4090
- eligibleCookies: options.advanced.crossSubDomainCookies.eligibleCookies,
4091
- domain: options.advanced.crossSubDomainCookies.domain
4092
- })
4093
- );
4094
4058
  }
4095
4059
  return plugins;
4096
4060
  }
package/dist/next-js.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Auth } from './index-hN0bCS_b.js';
1
+ import { a as Auth } from './index-Bkb3x6r0.js';
2
2
  import { U as User, S as Session } from './index-QaO4zgiz.js';
3
3
  import { NextRequest } from 'next/server';
4
4
  import 'zod';
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as http from 'http';
2
- import { a as Auth } from './index-hN0bCS_b.js';
2
+ import { a as Auth } from './index-Bkb3x6r0.js';
3
3
  import 'zod';
4
4
  import 'kysely';
5
5
  import './index-QaO4zgiz.js';
package/dist/plugins.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { A as AnonymousOptions, O as OrganizationOptions, b as Passkey, P as PasskeyOptions, U as UserWithPhoneNumber, e as anonymous, g as getPasskeyActions, m as magicLink, o as organization, p as passkey, c as passkeyClient, d as phoneNumber, t as twoFactor, a as twoFactorClient, u as username } from './index-BZV4xXJh.js';
1
+ export { A as AnonymousOptions, O as OrganizationOptions, b as Passkey, P as PasskeyOptions, U as UserWithPhoneNumber, e as anonymous, g as getPasskeyActions, m as magicLink, o as organization, p as passkey, c as passkeyClient, d as phoneNumber, t as twoFactor, a as twoFactorClient, u as username } from './index-JGsMiE1o.js';
2
2
  export { i as ac } from './index-DfAHOgpj.js';
3
- import { H as HookEndpointContext } from './index-hN0bCS_b.js';
4
- export { e as AuthEndpoint, f as AuthMiddleware, b as BetterAuthPlugin, P as PluginSchema, d as createAuthEndpoint, c as createAuthMiddleware, o as optionsMiddleware } from './index-hN0bCS_b.js';
3
+ import { H as HookEndpointContext } from './index-Bkb3x6r0.js';
4
+ export { e as AuthEndpoint, f as AuthMiddleware, b as BetterAuthPlugin, P as PluginSchema, d as createAuthEndpoint, c as createAuthMiddleware, o as optionsMiddleware } from './index-Bkb3x6r0.js';
5
5
  import './index-QaO4zgiz.js';
6
6
  import 'arctic';
7
7
  import 'zod';
package/dist/plugins.js CHANGED
@@ -749,7 +749,7 @@ var getDate = (span, unit = "ms") => {
749
749
  return new Date(date.getTime() + (unit === "sec" ? span * 1e3 : span));
750
750
  };
751
751
 
752
- // src/utils/cookies.ts
752
+ // src/cookies/index.ts
753
753
  import { TimeSpan } from "oslo";
754
754
  async function setSessionCookie(ctx, sessionToken, dontRememberMe, overrides) {
755
755
  const options = ctx.context.authCookies.sessionToken.options;
@@ -2854,6 +2854,11 @@ var csrfMiddleware = createAuthMiddleware(
2854
2854
  return;
2855
2855
  }
2856
2856
  const csrfToken = ctx.body?.csrfToken;
2857
+ if (!csrfToken) {
2858
+ throw new APIError9("UNAUTHORIZED", {
2859
+ message: "CSRF Token is required"
2860
+ });
2861
+ }
2857
2862
  const csrfCookie = await ctx.getSignedCookie(
2858
2863
  ctx.context.authCookies.csrfToken.name,
2859
2864
  ctx.context.secret
package/dist/react.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
3
3
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
4
4
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
5
5
  import { useStore } from '@nanostores/react';
6
- import './index-hN0bCS_b.js';
6
+ import './index-Bkb3x6r0.js';
7
7
  import 'kysely';
8
8
  import './index-QaO4zgiz.js';
9
9
  import 'arctic';
package/dist/react.js CHANGED
@@ -81,7 +81,6 @@ var addCurrentURL = {
81
81
  }
82
82
  }
83
83
  };
84
- var cache = /* @__PURE__ */ new Map();
85
84
  var csrfPlugin = {
86
85
  id: "csrf",
87
86
  name: "CSRF Check",
@@ -93,39 +92,36 @@ var csrfPlugin = {
93
92
  }
94
93
  if (options?.method !== "GET") {
95
94
  options = options || {};
96
- const csrfToken = cache.get("CSRF_TOKEN");
97
- if (!csrfToken) {
98
- const { data, error } = await betterFetch("/csrf", {
99
- body: void 0,
100
- baseURL: options.baseURL,
101
- plugins: [],
102
- method: "GET",
103
- credentials: "include",
104
- customFetchImpl: options.customFetchImpl
105
- });
106
- if (error) {
107
- if (error.status === 404) {
108
- throw new BetterAuthError(
109
- "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
110
- );
111
- }
112
- if (error.status === 429) {
113
- return new Response(
114
- JSON.stringify({
115
- message: "Too many requests. Please try again later."
116
- }),
117
- {
118
- status: 429,
119
- statusText: "Too Many Requests"
120
- }
121
- );
122
- }
95
+ const { data, error } = await betterFetch("/csrf", {
96
+ body: void 0,
97
+ baseURL: options.baseURL,
98
+ plugins: [],
99
+ method: "GET",
100
+ credentials: "include",
101
+ customFetchImpl: options.customFetchImpl
102
+ });
103
+ if (error) {
104
+ if (error.status === 404) {
123
105
  throw new BetterAuthError(
124
- "Failed to fetch CSRF token: " + error.message
106
+ "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
107
+ );
108
+ }
109
+ if (error.status === 429) {
110
+ return new Response(
111
+ JSON.stringify({
112
+ message: "Too many requests. Please try again later."
113
+ }),
114
+ {
115
+ status: 429,
116
+ statusText: "Too Many Requests"
117
+ }
125
118
  );
126
119
  }
127
- cache.set("CSRF_TOKEN", data.csrfToken);
120
+ throw new BetterAuthError(
121
+ "Failed to fetch CSRF token: " + error.message
122
+ );
128
123
  }
124
+ const csrfToken = data?.csrfToken;
129
125
  options.body = {
130
126
  ...options?.body,
131
127
  csrfToken
@@ -144,7 +140,7 @@ var getClientConfig = (options) => {
144
140
  method: "GET",
145
141
  ...options?.fetchOptions,
146
142
  plugins: [
147
- csrfPlugin,
143
+ ...!options?.disableCSRFTokenCheck ? [csrfPlugin] : [],
148
144
  redirectPlugin,
149
145
  addCurrentURL,
150
146
  ...options?.fetchOptions?.plugins?.filter((pl) => pl !== void 0) || [],
@@ -1,4 +1,4 @@
1
- import { a as Auth } from './index-hN0bCS_b.js';
1
+ import { a as Auth } from './index-Bkb3x6r0.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import './index-QaO4zgiz.js';
package/dist/solid.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
3
3
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
4
4
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
5
5
  import { Accessor } from 'solid-js';
6
- import './index-hN0bCS_b.js';
6
+ import './index-Bkb3x6r0.js';
7
7
  import 'kysely';
8
8
  import './index-QaO4zgiz.js';
9
9
  import 'arctic';
package/dist/solid.js CHANGED
@@ -81,7 +81,6 @@ var addCurrentURL = {
81
81
  }
82
82
  }
83
83
  };
84
- var cache = /* @__PURE__ */ new Map();
85
84
  var csrfPlugin = {
86
85
  id: "csrf",
87
86
  name: "CSRF Check",
@@ -93,39 +92,36 @@ var csrfPlugin = {
93
92
  }
94
93
  if (options?.method !== "GET") {
95
94
  options = options || {};
96
- const csrfToken = cache.get("CSRF_TOKEN");
97
- if (!csrfToken) {
98
- const { data, error } = await betterFetch("/csrf", {
99
- body: void 0,
100
- baseURL: options.baseURL,
101
- plugins: [],
102
- method: "GET",
103
- credentials: "include",
104
- customFetchImpl: options.customFetchImpl
105
- });
106
- if (error) {
107
- if (error.status === 404) {
108
- throw new BetterAuthError(
109
- "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
110
- );
111
- }
112
- if (error.status === 429) {
113
- return new Response(
114
- JSON.stringify({
115
- message: "Too many requests. Please try again later."
116
- }),
117
- {
118
- status: 429,
119
- statusText: "Too Many Requests"
120
- }
121
- );
122
- }
95
+ const { data, error } = await betterFetch("/csrf", {
96
+ body: void 0,
97
+ baseURL: options.baseURL,
98
+ plugins: [],
99
+ method: "GET",
100
+ credentials: "include",
101
+ customFetchImpl: options.customFetchImpl
102
+ });
103
+ if (error) {
104
+ if (error.status === 404) {
123
105
  throw new BetterAuthError(
124
- "Failed to fetch CSRF token: " + error.message
106
+ "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
107
+ );
108
+ }
109
+ if (error.status === 429) {
110
+ return new Response(
111
+ JSON.stringify({
112
+ message: "Too many requests. Please try again later."
113
+ }),
114
+ {
115
+ status: 429,
116
+ statusText: "Too Many Requests"
117
+ }
125
118
  );
126
119
  }
127
- cache.set("CSRF_TOKEN", data.csrfToken);
120
+ throw new BetterAuthError(
121
+ "Failed to fetch CSRF token: " + error.message
122
+ );
128
123
  }
124
+ const csrfToken = data?.csrfToken;
129
125
  options.body = {
130
126
  ...options?.body,
131
127
  csrfToken
@@ -144,7 +140,7 @@ var getClientConfig = (options) => {
144
140
  method: "GET",
145
141
  ...options?.fetchOptions,
146
142
  plugins: [
147
- csrfPlugin,
143
+ ...!options?.disableCSRFTokenCheck ? [csrfPlugin] : [],
148
144
  redirectPlugin,
149
145
  addCurrentURL,
150
146
  ...options?.fetchOptions?.plugins?.filter((pl) => pl !== void 0) || [],
@@ -1,4 +1,4 @@
1
- import { a as Auth, B as BetterAuthOptions } from './index-hN0bCS_b.js';
1
+ import { a as Auth, B as BetterAuthOptions } from './index-Bkb3x6r0.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import './index-QaO4zgiz.js';
package/dist/svelte.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as nanostores from 'nanostores';
3
3
  import * as _better_fetch_fetch from '@better-fetch/fetch';
4
4
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
5
5
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
6
- import './index-hN0bCS_b.js';
6
+ import './index-Bkb3x6r0.js';
7
7
  import 'kysely';
8
8
  import './index-QaO4zgiz.js';
9
9
  import 'arctic';
package/dist/svelte.js CHANGED
@@ -78,7 +78,6 @@ var addCurrentURL = {
78
78
  }
79
79
  }
80
80
  };
81
- var cache = /* @__PURE__ */ new Map();
82
81
  var csrfPlugin = {
83
82
  id: "csrf",
84
83
  name: "CSRF Check",
@@ -90,39 +89,36 @@ var csrfPlugin = {
90
89
  }
91
90
  if (options?.method !== "GET") {
92
91
  options = options || {};
93
- const csrfToken = cache.get("CSRF_TOKEN");
94
- if (!csrfToken) {
95
- const { data, error } = await betterFetch("/csrf", {
96
- body: void 0,
97
- baseURL: options.baseURL,
98
- plugins: [],
99
- method: "GET",
100
- credentials: "include",
101
- customFetchImpl: options.customFetchImpl
102
- });
103
- if (error) {
104
- if (error.status === 404) {
105
- throw new BetterAuthError(
106
- "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
107
- );
108
- }
109
- if (error.status === 429) {
110
- return new Response(
111
- JSON.stringify({
112
- message: "Too many requests. Please try again later."
113
- }),
114
- {
115
- status: 429,
116
- statusText: "Too Many Requests"
117
- }
118
- );
119
- }
92
+ const { data, error } = await betterFetch("/csrf", {
93
+ body: void 0,
94
+ baseURL: options.baseURL,
95
+ plugins: [],
96
+ method: "GET",
97
+ credentials: "include",
98
+ customFetchImpl: options.customFetchImpl
99
+ });
100
+ if (error) {
101
+ if (error.status === 404) {
120
102
  throw new BetterAuthError(
121
- "Failed to fetch CSRF token: " + error.message
103
+ "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
104
+ );
105
+ }
106
+ if (error.status === 429) {
107
+ return new Response(
108
+ JSON.stringify({
109
+ message: "Too many requests. Please try again later."
110
+ }),
111
+ {
112
+ status: 429,
113
+ statusText: "Too Many Requests"
114
+ }
122
115
  );
123
116
  }
124
- cache.set("CSRF_TOKEN", data.csrfToken);
117
+ throw new BetterAuthError(
118
+ "Failed to fetch CSRF token: " + error.message
119
+ );
125
120
  }
121
+ const csrfToken = data?.csrfToken;
126
122
  options.body = {
127
123
  ...options?.body,
128
124
  csrfToken
@@ -141,7 +137,7 @@ var getClientConfig = (options) => {
141
137
  method: "GET",
142
138
  ...options?.fetchOptions,
143
139
  plugins: [
144
- csrfPlugin,
140
+ ...!options?.disableCSRFTokenCheck ? [csrfPlugin] : [],
145
141
  redirectPlugin,
146
142
  addCurrentURL,
147
143
  ...options?.fetchOptions?.plugins?.filter((pl) => pl !== void 0) || [],
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as BetterAuthPlugin, a as Auth, I as InferFieldsInputClient, g as InferFieldsOutput } from './index-hN0bCS_b.js';
2
- export { A as Adapter, j as AdditionalSessionFieldsInput, k as AdditionalSessionFieldsOutput, h as AdditionalUserFieldsInput, i as AdditionalUserFieldsOutput, q as AuthContext, B as BetterAuthOptions, G as GenericEndpointContext, H as HookEndpointContext, n as InferPluginTypes, m as InferSession, l as InferUser, P as PluginSchema, R as RateLimit, S as SecondaryStorage, W as Where, p as init } from './index-hN0bCS_b.js';
1
+ import { b as BetterAuthPlugin, a as Auth, I as InferFieldsInputClient, g as InferFieldsOutput } from './index-Bkb3x6r0.js';
2
+ export { A as Adapter, j as AdditionalSessionFieldsInput, k as AdditionalSessionFieldsOutput, h as AdditionalUserFieldsInput, i as AdditionalUserFieldsOutput, q as AuthContext, B as BetterAuthOptions, G as GenericEndpointContext, H as HookEndpointContext, n as InferPluginTypes, m as InferSession, l as InferUser, P as PluginSchema, R as RateLimit, S as SecondaryStorage, W as Where, p as init } from './index-Bkb3x6r0.js';
3
3
  import { U as UnionToIntersection, H as HasRequiredKeys, P as Prettify, S as StripEmptyObjects, L as LiteralString } from './helper-DPDj8Nix.js';
4
4
  export { D as DeepPartial, a as LiteralUnion, R as RequiredKeysOf, W as WithoutEmpty } from './helper-DPDj8Nix.js';
5
5
  import { S as Session, U as User } from './index-QaO4zgiz.js';
@@ -102,6 +102,7 @@ interface ClientOptions {
102
102
  fetchOptions?: BetterFetchOption;
103
103
  plugins?: BetterAuthClientPlugin[];
104
104
  baseURL?: string;
105
+ disableCSRFTokenCheck?: boolean;
105
106
  }
106
107
  type InferClientAPI<O extends ClientOptions> = InferRoutes<O["plugins"] extends Array<any> ? (O["plugins"] extends Array<infer Pl> ? UnionToIntersection<Pl extends {
107
108
  $InferServerPlugin: infer Plug;
package/dist/vue.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
3
3
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
4
4
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
5
5
  import { Ref, DeepReadonly } from 'vue';
6
- import './index-hN0bCS_b.js';
6
+ import './index-Bkb3x6r0.js';
7
7
  import 'kysely';
8
8
  import './index-QaO4zgiz.js';
9
9
  import 'arctic';
package/dist/vue.js CHANGED
@@ -81,7 +81,6 @@ var addCurrentURL = {
81
81
  }
82
82
  }
83
83
  };
84
- var cache = /* @__PURE__ */ new Map();
85
84
  var csrfPlugin = {
86
85
  id: "csrf",
87
86
  name: "CSRF Check",
@@ -93,39 +92,36 @@ var csrfPlugin = {
93
92
  }
94
93
  if (options?.method !== "GET") {
95
94
  options = options || {};
96
- const csrfToken = cache.get("CSRF_TOKEN");
97
- if (!csrfToken) {
98
- const { data, error } = await betterFetch("/csrf", {
99
- body: void 0,
100
- baseURL: options.baseURL,
101
- plugins: [],
102
- method: "GET",
103
- credentials: "include",
104
- customFetchImpl: options.customFetchImpl
105
- });
106
- if (error) {
107
- if (error.status === 404) {
108
- throw new BetterAuthError(
109
- "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
110
- );
111
- }
112
- if (error.status === 429) {
113
- return new Response(
114
- JSON.stringify({
115
- message: "Too many requests. Please try again later."
116
- }),
117
- {
118
- status: 429,
119
- statusText: "Too Many Requests"
120
- }
121
- );
122
- }
95
+ const { data, error } = await betterFetch("/csrf", {
96
+ body: void 0,
97
+ baseURL: options.baseURL,
98
+ plugins: [],
99
+ method: "GET",
100
+ credentials: "include",
101
+ customFetchImpl: options.customFetchImpl
102
+ });
103
+ if (error) {
104
+ if (error.status === 404) {
123
105
  throw new BetterAuthError(
124
- "Failed to fetch CSRF token: " + error.message
106
+ "CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth)."
107
+ );
108
+ }
109
+ if (error.status === 429) {
110
+ return new Response(
111
+ JSON.stringify({
112
+ message: "Too many requests. Please try again later."
113
+ }),
114
+ {
115
+ status: 429,
116
+ statusText: "Too Many Requests"
117
+ }
125
118
  );
126
119
  }
127
- cache.set("CSRF_TOKEN", data.csrfToken);
120
+ throw new BetterAuthError(
121
+ "Failed to fetch CSRF token: " + error.message
122
+ );
128
123
  }
124
+ const csrfToken = data?.csrfToken;
129
125
  options.body = {
130
126
  ...options?.body,
131
127
  csrfToken
@@ -144,7 +140,7 @@ var getClientConfig = (options) => {
144
140
  method: "GET",
145
141
  ...options?.fetchOptions,
146
142
  plugins: [
147
- csrfPlugin,
143
+ ...!options?.disableCSRFTokenCheck ? [csrfPlugin] : [],
148
144
  redirectPlugin,
149
145
  addCurrentURL,
150
146
  ...options?.fetchOptions?.plugins?.filter((pl) => pl !== void 0) || [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-auth",
3
- "version": "0.3.5-beta.7",
3
+ "version": "0.3.5-beta.8",
4
4
  "description": "The most comprehensive authentication library for TypeScript.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -65,7 +65,6 @@
65
65
  "vue": "^3.5.0"
66
66
  },
67
67
  "dependencies": {
68
- "@antfu/ni": "^0.23.0",
69
68
  "@babel/preset-react": "^7.24.7",
70
69
  "@babel/preset-typescript": "^7.24.7",
71
70
  "@better-fetch/fetch": "^1.1.9",
@@ -82,7 +81,7 @@
82
81
  "@simplewebauthn/browser": "^10.0.0",
83
82
  "@simplewebauthn/server": "^10.0.1",
84
83
  "arctic": "2.0.0-next.9",
85
- "better-call": "0.2.5-beta.4",
84
+ "better-call": "0.2.5",
86
85
  "c12": "^1.11.2",
87
86
  "chalk": "^5.3.0",
88
87
  "commander": "^12.1.0",
@@ -91,12 +90,10 @@
91
90
  "dotenv": "^16.4.5",
92
91
  "execa": "^9.4.0",
93
92
  "jose": "^5.7.0",
94
- "js-base64": "^3.7.7",
95
93
  "kysely": "^0.27.4",
96
94
  "nanoid": "^5.0.7",
97
95
  "nanoquery": "^1.3.0",
98
96
  "nanostores": "^0.11.2",
99
- "oauth4webapi": "^2.12.0",
100
97
  "ora": "^8.0.1",
101
98
  "oslo": "^1.2.1",
102
99
  "prompts": "^2.4.2",
@@ -111,6 +108,7 @@
111
108
  "dev": "NODE_OPTIONS='--max-old-space-size=4000' tsup --watch --sourcemap",
112
109
  "dev:dts": "NODE_OPTIONS='--max-old-space-size=8192' tsup --watch --dts",
113
110
  "test": "pnpm prisma:push && pnpm typecheck && vitest",
111
+ "vitest": "vitest",
114
112
  "prisma:push": "prisma db push --schema src/adapters/prisma-adapter/test/schema.prisma",
115
113
  "test:adapters": "pnpm prisma:push && vitest adapters",
116
114
  "bump": "bumpp",