@take-out/better-auth-utils 0.0.67 → 0.0.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,6 @@
1
1
  # @take-out/better-auth-utils
2
2
 
3
- Better Auth utilities and helpers for React/React Native applications.
4
-
5
- ## Features
6
-
7
- - JWT support for Zero, web and React Native
8
- - Session persistence in local storage
9
- - Token validation and refresh
10
- - State management with emitters
11
- - Automatic retry on authentication errors
12
- - TypeScript support with full type safety
3
+ Auth utilities for better-auth with React/React Native support.
13
4
 
14
5
  ## Installation
15
6
 
@@ -17,120 +8,99 @@ Better Auth utilities and helpers for React/React Native applications.
17
8
  bun add @take-out/better-auth-utils
18
9
  ```
19
10
 
20
- ## Usage
21
-
22
- ### Basic Setup
11
+ ## Client Usage
23
12
 
24
13
  ```typescript
25
14
  import { createBetterAuthClient } from '@take-out/better-auth-utils'
26
- import { adminClient, magicLinkClient } from 'better-auth/client/plugins'
27
-
28
- const authClient = createBetterAuthClient({
29
- baseURL: 'https://your-app.com',
30
- plugins: [adminClient(), magicLinkClient()],
31
- // Optional callbacks
32
- onAuthStateChange: (state) => {
33
- console.info('Auth state changed:', state)
34
- },
35
- onAuthError: (error) => {
36
- console.error('Auth error:', error)
37
- },
38
- })
39
15
 
40
- // Export for use throughout your app
41
- export const {
42
- authClient,
43
- useAuth,
44
- getAuth,
45
- setAuthClientToken,
46
- clearAuthClientToken,
47
- } = authClient
48
- ```
49
-
50
- ### Using in React Components
16
+ const auth = createBetterAuthClient({
17
+ baseURL: 'https://myapp.com',
18
+ plugins: [/* better-auth plugins */],
19
+ // transform user object with app-specific fields
20
+ createUser: (user) => ({ ...user, role: user.role as 'admin' | undefined }),
21
+ // optional callbacks
22
+ onAuthStateChange: (state) => console.log('Auth changed:', state),
23
+ onAuthError: (error) => console.error('Auth error:', error),
24
+ })
51
25
 
52
- ```tsx
53
- import { useAuth } from './auth'
26
+ // React hook for auth state
27
+ const { state, user, token } = auth.useAuth()
54
28
 
55
- function UserProfile() {
56
- const { user, state } = useAuth()
29
+ // get current auth state (non-reactive)
30
+ const { loggedIn } = auth.getAuth()
57
31
 
58
- if (state === 'loading') return <div>Loading...</div>
59
- if (state === 'logged-out') return <div>Please log in</div>
32
+ // clear all auth (localStorage + cookies)
33
+ auth.clearAllAuth()
60
34
 
61
- return <div>Welcome, {user?.name}!</div>
62
- }
35
+ // clear just localStorage token
36
+ auth.clearAuthClientToken()
63
37
  ```
64
38
 
65
- ### Custom User Types
39
+ ### Client Options
40
+
41
+ | Option | Type | Default | Description |
42
+ |--------|------|---------|-------------|
43
+ | `baseURL` | `string` | required | Auth server URL |
44
+ | `plugins` | `array` | `[]` | better-auth client plugins |
45
+ | `createUser` | `function` | identity | Transform user object with app-specific typing |
46
+ | `onAuthStateChange` | `function` | - | Callback when auth state changes |
47
+ | `onAuthError` | `function` | - | Callback for auth errors |
48
+ | `storagePrefix` | `string` | `'auth'` | localStorage key prefix |
49
+ | `retryDelay` | `number` | `4000` | Retry delay after errors (ms) |
50
+ | `tokenValidationEndpoint` | `string` | `'/api/auth/validateToken'` | JWT validation endpoint |
51
+ | `authCookieNames` | `string[]` | `['better-auth.jwt', 'better-auth.session_token']` | Cookie names to clear on `clearAllAuth()` |
52
+
53
+ ### Client API
54
+
55
+ - `useAuth()` - React hook returning `{ state, user, session, token }`
56
+ - `getAuth()` - Get current auth state (non-reactive), includes `loggedIn` boolean
57
+ - `setAuthClientToken({ token, session })` - Set auth token and session
58
+ - `clearAuthClientToken()` - Clear localStorage token only
59
+ - `clearAllAuth()` - Clear localStorage AND cookies
60
+ - `clearState()` - Clear all auth state and storage
61
+ - `getValidToken()` - Get valid JWT, refreshing if needed
62
+ - `authState` - Emitter for subscribing to auth changes
63
+ - `authClientVersion` - Emitter that updates when auth client recreates
64
+
65
+ ## Server Usage
66
66
 
67
67
  ```typescript
68
- import type { User } from '@take-out/better-auth-utils'
69
-
70
- interface MyUser extends User {
71
- role?: 'admin' | 'user'
72
- preferences?: {
73
- theme: 'light' | 'dark'
68
+ import {
69
+ validateToken,
70
+ isValidJWT,
71
+ InvalidTokenError,
72
+ } from '@take-out/better-auth-utils/server'
73
+
74
+ // validate JWT against JWKS endpoint
75
+ try {
76
+ const payload = await validateToken(token, {
77
+ baseUrl: 'https://myapp.com',
78
+ forceIssuer: process.env.FORCE_ISSUER, // optional, for CI
79
+ jwksPath: '/api/auth/jwks', // optional, default
80
+ })
81
+ console.log('User ID:', payload.sub)
82
+ } catch (err) {
83
+ if (err instanceof InvalidTokenError) {
84
+ // token invalid (malformed, expired, signature mismatch, etc)
85
+ return Response.json({ error: 'INVALID_TOKEN' }, { status: 401 })
74
86
  }
75
87
  }
76
88
 
77
- const authClient = createBetterAuthClient<any, MyUser>({
78
- baseURL: 'https://your-app.com',
79
- })
89
+ // simple boolean check
90
+ const valid = await isValidJWT(token, { baseUrl: 'https://myapp.com' })
80
91
  ```
81
92
 
82
- ### Configuration Options
83
-
84
- - `baseURL` - The base URL for your auth server
85
- - `plugins` - Array of better-auth plugins
86
- - `onAuthStateChange` - Callback when auth state changes
87
- - `onAuthError` - Callback for handling auth errors
88
- - `storagePrefix` - Prefix for local storage keys (default: 'auth')
89
- - `retryDelay` - Delay in ms after auth errors (default: 4000)
90
- - `tokenValidationEndpoint` - Custom token validation endpoint (default:
91
- '/api/auth/validateToken')
92
-
93
- ## API
94
-
95
- ### `createBetterAuthClient(options)`
96
-
97
- Creates a new authentication client with the provided options.
93
+ ### Server Exports
98
94
 
99
- ### `useAuth()`
95
+ | Export | Description |
96
+ |--------|-------------|
97
+ | `validateToken(token, options)` | Validate JWT against JWKS, returns payload |
98
+ | `isValidJWT(token, options)` | Boolean validation check |
99
+ | `InvalidTokenError` | Error thrown for invalid tokens |
100
100
 
101
- React hook that returns the current authentication state.
101
+ ### JWKS Validation
102
102
 
103
- ### `getAuth()`
104
-
105
- Gets the current authentication state (non-reactive).
106
-
107
- ### `setAuthClientToken({ token, session })`
108
-
109
- Sets the authentication token and session.
110
-
111
- ### `clearAuthClientToken()`
112
-
113
- Clears the stored authentication token.
114
-
115
- ### `clearState()`
116
-
117
- Clears all authentication state and storage.
118
-
119
- ## Development
120
-
121
- ```bash
122
- # Install dependencies
123
- bun install
124
-
125
- # Build the package
126
- bun run build
127
-
128
- # Run in watch mode
129
- bun run watch
130
-
131
- # Lint the code
132
- bun run lint:fix
133
- ```
103
+ The server validates JWTs against the JWKS endpoint (`/api/auth/jwks` by default). A fresh JWKS is fetched for each validation to avoid stale key cache issues.
134
104
 
135
105
  ## License
136
106
 
@@ -32,7 +32,8 @@ function createBetterAuthClient(options) {
32
32
  createUser,
33
33
  storagePrefix = "auth",
34
34
  retryDelay = 4e3,
35
- tokenValidationEndpoint = "/api/auth/validateToken",
35
+ useJWT = !1,
36
+ authCookieNames = ["better-auth.jwt", "better-auth.session_token"],
36
37
  ...authClientOptions
37
38
  } = options,
38
39
  empty = {
@@ -41,19 +42,25 @@ function createBetterAuthClient(options) {
41
42
  user: null,
42
43
  token: null
43
44
  },
45
+ keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`),
46
+ stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`),
44
47
  createAuthClientWithSession = session => (0, import_client.createAuthClient)({
45
48
  ...authClientOptions,
46
49
  fetchOptions: {
47
- headers: {
50
+ credentials: "include",
51
+ headers: useJWT ? {
48
52
  Authorization: `Bearer ${session}`
49
- }
53
+ } : void 0
50
54
  }
51
- }),
52
- keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`),
53
- stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`);
55
+ });
54
56
  let authClient = (() => {
55
57
  const existingSession = keysStorage.get()?.session;
56
- return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)(authClientOptions);
58
+ return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)({
59
+ ...authClientOptions,
60
+ fetchOptions: {
61
+ credentials: "include"
62
+ }
63
+ });
57
64
  })();
58
65
  const authState = (0, import_helpers.createEmitter)("authState", stateStorage.get() || empty, {
59
66
  comparator: import_helpers.isEqualDeepLite
@@ -67,6 +74,9 @@ function createBetterAuthClient(options) {
67
74
  stateStorage.set(next), authState.emit(next), next.token && next.session ? keysStorage.set({
68
75
  token: next.token,
69
76
  session: next.session.token
77
+ }) : next.session ? keysStorage.set({
78
+ token: "",
79
+ session: next.session.token
70
80
  }) : keysStorage.set({
71
81
  token: "",
72
82
  session: ""
@@ -97,15 +107,19 @@ function createBetterAuthClient(options) {
97
107
  sessionUpdate = nextState === "loading" ? {} : {
98
108
  session: data?.session ?? null,
99
109
  user: data?.user ? createUser ? createUser(data.user) : data.user : null
100
- };
110
+ },
111
+ previousSession = authState.value?.session,
112
+ isNewSession = data?.session && (!previousSession || previousSession.id !== data.session.id || previousSession.userId !== data.session.userId);
101
113
  setState({
102
114
  state: nextState,
103
115
  ...sessionUpdate
104
- }), data?.session && !authState.value.token && getValidToken().then(token => {
116
+ }), useJWT && data?.session && (isNewSession || !authState.value.token) && (isNewSession && authState.value.token && setState({
117
+ token: null
118
+ }), getValidToken().then(token => {
105
119
  token && setState({
106
120
  token
107
121
  });
108
- });
122
+ }));
109
123
  });
110
124
  }
111
125
  function scheduleAuthRetry(delayMs) {
@@ -114,20 +128,6 @@ function createBetterAuthClient(options) {
114
128
  }, delayMs);
115
129
  }
116
130
  async function getValidToken() {
117
- const existing = keysStorage.get()?.token;
118
- if (existing) try {
119
- if ((await fetch(tokenValidationEndpoint, {
120
- method: "POST",
121
- headers: {
122
- "Content-Type": "application/json"
123
- },
124
- body: JSON.stringify({
125
- token: existing
126
- })
127
- }).then(res2 => res2.json()))?.valid) return existing;
128
- } catch (error) {
129
- console.error("Error validating token:", error);
130
- }
131
131
  const res = await authClient.$fetch("/token");
132
132
  if (res.error) {
133
133
  console.error(`Error fetching token: ${res.error.statusText}`);
@@ -136,9 +136,19 @@ function createBetterAuthClient(options) {
136
136
  return res.data?.token;
137
137
  }
138
138
  const clearAuthClientToken = () => {
139
- keysStorage.remove();
140
- },
141
- getAuth = () => {
139
+ keysStorage.remove();
140
+ };
141
+ function clearAuthCookies() {
142
+ if (!(typeof document > "u")) for (const cookieName of authCookieNames) {
143
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
144
+ const domain = window.location.hostname;
145
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain}`, domain.startsWith(".") && (document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain.slice(1)}`);
146
+ }
147
+ }
148
+ function clearAllAuth() {
149
+ clearAuthCookies(), clearState();
150
+ }
151
+ const getAuth = () => {
142
152
  const state = authState?.value || empty;
143
153
  return {
144
154
  ...state,
@@ -169,6 +179,7 @@ function createBetterAuthClient(options) {
169
179
  authClient: proxiedAuthClient,
170
180
  setAuthClientToken,
171
181
  clearAuthClientToken,
182
+ clearAllAuth,
172
183
  useAuth,
173
184
  getAuth,
174
185
  getValidToken,
@@ -25,40 +25,41 @@ function createBetterAuthClient(options) {
25
25
  createUser,
26
26
  storagePrefix = "auth",
27
27
  retryDelay = 4e3,
28
- tokenValidationEndpoint = "/api/auth/validateToken",
28
+ useJWT = !1,
29
+ authCookieNames = ["better-auth.jwt", "better-auth.session_token"],
29
30
  ...authClientOptions
30
31
  } = options, empty = {
31
32
  state: "logged-out",
32
33
  session: null,
33
34
  user: null,
34
35
  token: null
35
- }, createAuthClientWithSession = (session) => (0, import_client.createAuthClient)({
36
+ }, keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`), stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`), createAuthClientWithSession = (session) => (0, import_client.createAuthClient)({
36
37
  ...authClientOptions,
37
38
  fetchOptions: {
38
- headers: {
39
- Authorization: `Bearer ${session}`
40
- }
39
+ credentials: "include",
40
+ headers: useJWT ? { Authorization: `Bearer ${session}` } : void 0
41
41
  }
42
- }), keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`), stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`);
42
+ });
43
43
  let authClient = (() => {
44
44
  const existingSession = keysStorage.get()?.session;
45
- return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)(authClientOptions);
45
+ return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)({
46
+ ...authClientOptions,
47
+ fetchOptions: { credentials: "include" }
48
+ });
46
49
  })();
47
50
  const authState = (0, import_helpers.createEmitter)(
48
51
  "authState",
49
52
  stateStorage.get() || empty,
50
- {
51
- comparator: import_helpers.isEqualDeepLite
52
- }
53
+ { comparator: import_helpers.isEqualDeepLite }
53
54
  ), authClientVersion = (0, import_helpers.createEmitter)("authClientVersion", 0), setState = (update) => {
54
55
  const next = { ...authState.value, ...update };
55
56
  stateStorage.set(next), authState.emit(next), next.token && next.session ? keysStorage.set({
56
57
  token: next.token,
57
58
  session: next.session.token
58
- }) : keysStorage.set({
59
+ }) : next.session ? keysStorage.set({
59
60
  token: "",
60
- session: ""
61
- }), onAuthStateChange?.(next);
61
+ session: next.session.token
62
+ }) : keysStorage.set({ token: "", session: "" }), onAuthStateChange?.(next);
62
63
  }, setAuthClientToken = async (props) => {
63
64
  keysStorage.set(props), updateAuthClient(props.session);
64
65
  };
@@ -76,13 +77,13 @@ function createBetterAuthClient(options) {
76
77
  const data = dataGeneric, hasPersistedSession = !!keysStorage.get()?.session, nextState = isPending ? "loading" : data?.session ? "logged-in" : hasPersistedSession && data === void 0 ? "loading" : "logged-out", sessionUpdate = nextState === "loading" ? {} : {
77
78
  session: data?.session ?? null,
78
79
  user: data?.user ? createUser ? createUser(data.user) : data.user : null
79
- };
80
+ }, previousSession = authState.value?.session, isNewSession = data?.session && (!previousSession || previousSession.id !== data.session.id || previousSession.userId !== data.session.userId);
80
81
  setState({
81
82
  state: nextState,
82
83
  ...sessionUpdate
83
- }), data?.session && !authState.value.token && getValidToken().then((token) => {
84
+ }), useJWT && data?.session && (isNewSession || !authState.value.token) && (isNewSession && authState.value.token && setState({ token: null }), getValidToken().then((token) => {
84
85
  token && setState({ token });
85
- });
86
+ }));
86
87
  });
87
88
  }
88
89
  function scheduleAuthRetry(delayMs) {
@@ -91,22 +92,6 @@ function createBetterAuthClient(options) {
91
92
  }, delayMs);
92
93
  }
93
94
  async function getValidToken() {
94
- const existing = keysStorage.get()?.token;
95
- if (existing)
96
- try {
97
- if ((await fetch(tokenValidationEndpoint, {
98
- method: "POST",
99
- headers: {
100
- "Content-Type": "application/json"
101
- },
102
- body: JSON.stringify({
103
- token: existing
104
- })
105
- }).then((res2) => res2.json()))?.valid)
106
- return existing;
107
- } catch (error) {
108
- console.error("Error validating token:", error);
109
- }
110
95
  const res = await authClient.$fetch("/token");
111
96
  if (res.error) {
112
97
  console.error(`Error fetching token: ${res.error.statusText}`);
@@ -116,12 +101,21 @@ function createBetterAuthClient(options) {
116
101
  }
117
102
  const clearAuthClientToken = () => {
118
103
  keysStorage.remove();
119
- }, getAuth = () => {
104
+ };
105
+ function clearAuthCookies() {
106
+ if (!(typeof document > "u"))
107
+ for (const cookieName of authCookieNames) {
108
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
109
+ const domain = window.location.hostname;
110
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain}`, domain.startsWith(".") && (document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain.slice(1)}`);
111
+ }
112
+ }
113
+ function clearAllAuth() {
114
+ clearAuthCookies(), clearState();
115
+ }
116
+ const getAuth = () => {
120
117
  const state = authState?.value || empty;
121
- return {
122
- ...state,
123
- loggedIn: !!state.session
124
- };
118
+ return { ...state, loggedIn: !!state.session };
125
119
  }, useAuth = () => (0, import_helpers.useEmitterValue)(authState) || empty;
126
120
  function clearState() {
127
121
  keysStorage.remove(), stateStorage.remove(), setState(empty);
@@ -146,6 +140,7 @@ function createBetterAuthClient(options) {
146
140
  authClient: proxiedAuthClient,
147
141
  setAuthClientToken,
148
142
  clearAuthClientToken,
143
+ clearAllAuth,
149
144
  useAuth,
150
145
  getAuth,
151
146
  getValidToken,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/createAuthClient.ts"],
4
- "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,qBAMO,8BACP,gBAA+D;AAqExD,SAAS,uBACd,SACoF;AAEpF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,0BAA0B;AAAA,IAC1B,GAAG;AAAA,EACL,IAAI,SAEE,QAA0B;AAAA,IAC9B,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,EACT,GAEM,8BAA8B,CAAC,gBAC5B,gCAAiB;AAAA,IACtB,GAAG;AAAA,IACH,cAAc;AAAA,MACZ,SAAS;AAAA,QACP,eAAe,UAAU,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAC,GAGG,kBAAc,mCAAgC,GAAG,aAAa,OAAO,GACrE,mBAAe,mCAAqC,GAAG,aAAa,QAAQ;AAElF,MAAI,cAAc,MAAM;AACtB,UAAM,kBAAkB,YAAY,IAAI,GAAG;AAC3C,WAAO,kBACH,4BAA4B,eAAe,QAC3C,gCAAiB,iBAAyB;AAAA,EAChD,GAAG;AAEH,QAAM,gBAAY;AAAA,IAChB;AAAA,IACA,aAAa,IAAI,KAAK;AAAA,IACtB;AAAA,MACE,YAAY;AAAA,IACd;AAAA,EACF,GAEM,wBAAoB,8BAAsB,qBAAqB,CAAC,GAEhE,WAAW,CAAC,WAAsC;AAEtD,UAAM,OAAO,EAAE,GADC,UAAU,OACC,GAAG,OAAO;AACrC,iBAAa,IAAI,IAAI,GACrB,UAAU,KAAK,IAAI,GAGf,KAAK,SAAS,KAAK,UACrB,YAAY,IAAI;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK,QAAQ;AAAA,IACxB,CAAC,IAED,YAAY,IAAI;AAAA,MACd,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC,GAIH,oBAAoB,IAAI;AAAA,EAC1B,GAEM,qBAAqB,OAAO,UAA8C;AAC9E,gBAAY,IAAI,KAAK,GACrB,iBAAiB,MAAM,OAAO;AAAA,EAChC;AAEA,WAAS,iBAAiB,SAAiB;AACzC,iBAAa,4BAA4B,OAAO,GAChD,kBAAkB,KAAK,KAAK,OAAO,CAAC,GACpC,sBAAsB;AAAA,EACxB;AAEA,MAAI,UAA2B,MAC3B,aAAmD;AAEvD,WAAS,wBAAwB;AAC/B,cAAU,GAEV,UAAU,WAAW,WAAW,UAAU,OAAO,UAAU;AACzD,YAAM,EAAE,MAAM,aAAa,WAAW,MAAM,IAAI;AAEhD,UAAI,OAAO;AACT,sBAAc,KAAK,GAEnB,kBAAkB,UAAU;AAC5B;AAAA,MACF;AAEA,YAAM,OAAO,aAUP,sBAAsB,CAAC,CAAC,YAAY,IAAI,GAAG,SAC3C,YAAY,YACd,YACA,MAAM,UACJ,cACA,uBAAuB,SAAS,SAC9B,YACA,cAIF,gBACJ,cAAc,YACV,CAAC,IACD;AAAA,QACE,SAAS,MAAM,WAAW;AAAA,QAC1B,MAAM,MAAM,OAAQ,aAAa,WAAW,KAAK,IAAI,IAAI,KAAK,OAAQ;AAAA,MACxE;AAEN,eAAS;AAAA,QACP,OAAO;AAAA,QACP,GAAG;AAAA,MACL,CAAC,GAGG,MAAM,WAAW,CAAC,UAAU,MAAM,SACpC,cAAc,EAAE,KAAK,CAAC,UAAU;AAC9B,QAAI,SACF,SAAS,EAAE,MAAM,CAAC;AAAA,MAEtB,CAAC;AAAA,IAEL,CAAC;AAAA,EACH;AAEA,WAAS,kBAAkB,SAAiB;AAC1C,IAAI,cACF,aAAa,UAAU,GAEzB,aAAa,WAAW,MAAM;AAC5B,mBAAa,MACb,sBAAsB;AAAA,IACxB,GAAG,OAAO;AAAA,EACZ;AAEA,iBAAe,gBAA6C;AAC1D,UAAM,WAAW,YAAY,IAAI,GAAG;AAEpC,QAAI;AACF,UAAI;AAWF,aAViB,MAAM,MAAM,yBAAyB;AAAA,UACpD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,OAAO;AAAA,UACT,CAAC;AAAA,QACH,CAAC,EAAE,KAAK,CAACA,SAAQA,KAAI,KAAK,CAAC,IAEb;AACZ,iBAAO;AAAA,MAEX,SAAS,OAAO;AACd,gBAAQ,MAAM,2BAA2B,KAAK;AAAA,MAChD;AAGF,UAAM,MAAM,MAAM,WAAW,OAAO,QAAQ;AAC5C,QAAI,IAAI,OAAO;AACb,cAAQ,MAAM,yBAAyB,IAAI,MAAM,UAAU,EAAE;AAC7D;AAAA,IACF;AAEA,WADa,IAAI,MACJ;AAAA,EACf;AAEA,QAAM,uBAAuB,MAAM;AACjC,gBAAY,OAAO;AAAA,EACrB,GAEM,UAAU,MAAM;AACpB,UAAM,QAAQ,WAAW,SAAS;AAClC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,CAAC,CAAC,MAAM;AAAA,IACpB;AAAA,EACF,GAEM,UAAU,UACP,gCAAgB,SAAS,KAAK;AAGvC,WAAS,aAAa;AACpB,gBAAY,OAAO,GACnB,aAAa,OAAO,GACpB,SAAS,KAAK;AAAA,EAChB;AAMA,MAHA,sBAAsB,GAGlB,OAAO,SAAW,OAAe,OAAO,kBAAkB;AAC5D,UAAM,UAAU,MAAM;AACpB,gBAAU,GACN,cACF,aAAa,UAAU;AAAA,IAE3B;AACA,WAAO,iBAAiB,gBAAgB,OAAO;AAAA,EACjD;AAEA,QAAM,oBAAoB,IAAI,MAAM,YAAY;AAAA,IAC9C,IAAI,SAAS,KAAK;AAChB,aAAI,QAAQ,YACH,MAAM;AACX,mBAAW,GAKX,WAAW,UAAU,GAGjB,OAAO,SAAW,OACpB,OAAO,UAAU,SAAS;AAAA,MAE9B,IAGK,QAAQ,IAAI,YAAY,GAAG;AAAA,IACpC;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
5
- "names": ["res"]
4
+ "mappings": "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",
5
+ "names": []
6
6
  }
@@ -34,7 +34,8 @@ function createBetterAuthClient(options) {
34
34
  createUser,
35
35
  storagePrefix = "auth",
36
36
  retryDelay = 4e3,
37
- tokenValidationEndpoint = "/api/auth/validateToken",
37
+ useJWT = !1,
38
+ authCookieNames = ["better-auth.jwt", "better-auth.session_token"],
38
39
  ...authClientOptions
39
40
  } = options,
40
41
  empty = {
@@ -43,22 +44,28 @@ function createBetterAuthClient(options) {
43
44
  user: null,
44
45
  token: null
45
46
  },
47
+ keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`),
48
+ stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`),
46
49
  createAuthClientWithSession = function (session) {
47
50
  return (0, import_client.createAuthClient)({
48
51
  ...authClientOptions,
49
52
  fetchOptions: {
50
- headers: {
53
+ credentials: "include",
54
+ headers: useJWT ? {
51
55
  Authorization: `Bearer ${session}`
52
- }
56
+ } : void 0
53
57
  }
54
58
  });
55
59
  },
56
- keysStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-keys`),
57
- stateStorage = (0, import_helpers.createStorageValue)(`${storagePrefix}-state`),
58
60
  authClient = function () {
59
61
  var _keysStorage_get,
60
62
  existingSession = (_keysStorage_get = keysStorage.get()) === null || _keysStorage_get === void 0 ? void 0 : _keysStorage_get.session;
61
- return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)(authClientOptions);
63
+ return existingSession ? createAuthClientWithSession(existingSession) : (0, import_client.createAuthClient)({
64
+ ...authClientOptions,
65
+ fetchOptions: {
66
+ credentials: "include"
67
+ }
68
+ });
62
69
  }(),
63
70
  authState = (0, import_helpers.createEmitter)("authState", stateStorage.get() || empty, {
64
71
  comparator: import_helpers.isEqualDeepLite
@@ -73,6 +80,9 @@ function createBetterAuthClient(options) {
73
80
  stateStorage.set(next), authState.emit(next), next.token && next.session ? keysStorage.set({
74
81
  token: next.token,
75
82
  session: next.session.token
83
+ }) : next.session ? keysStorage.set({
84
+ token: "",
85
+ session: next.session.token
76
86
  }) : keysStorage.set({
77
87
  token: "",
78
88
  session: ""
@@ -89,6 +99,7 @@ function createBetterAuthClient(options) {
89
99
  function subscribeToAuthEffect() {
90
100
  dispose?.(), dispose = authClient.useSession.subscribe(async function (props) {
91
101
  var _keysStorage_get,
102
+ _authState_value,
92
103
  {
93
104
  data: dataGeneric,
94
105
  isPending,
@@ -105,15 +116,19 @@ function createBetterAuthClient(options) {
105
116
  sessionUpdate = nextState === "loading" ? {} : {
106
117
  session: (_data_session = data?.session) !== null && _data_session !== void 0 ? _data_session : null,
107
118
  user: data?.user ? createUser ? createUser(data.user) : data.user : null
108
- };
119
+ },
120
+ previousSession = (_authState_value = authState.value) === null || _authState_value === void 0 ? void 0 : _authState_value.session,
121
+ isNewSession = data?.session && (!previousSession || previousSession.id !== data.session.id || previousSession.userId !== data.session.userId);
109
122
  setState({
110
123
  state: nextState,
111
124
  ...sessionUpdate
112
- }), data?.session && !authState.value.token && getValidToken().then(function (token) {
125
+ }), useJWT && data?.session && (isNewSession || !authState.value.token) && (isNewSession && authState.value.token && setState({
126
+ token: null
127
+ }), getValidToken().then(function (token) {
113
128
  token && setState({
114
129
  token
115
130
  });
116
- });
131
+ }));
117
132
  });
118
133
  }
119
134
  function scheduleAuthRetry(delayMs) {
@@ -122,36 +137,44 @@ function createBetterAuthClient(options) {
122
137
  }, delayMs);
123
138
  }
124
139
  async function getValidToken() {
125
- var _keysStorage_get,
126
- existing = (_keysStorage_get = keysStorage.get()) === null || _keysStorage_get === void 0 ? void 0 : _keysStorage_get.token;
127
- if (existing) try {
128
- var response = await fetch(tokenValidationEndpoint, {
129
- method: "POST",
130
- headers: {
131
- "Content-Type": "application/json"
132
- },
133
- body: JSON.stringify({
134
- token: existing
135
- })
136
- }).then(function (res2) {
137
- return res2.json();
138
- });
139
- if (response?.valid) return existing;
140
- } catch (error) {
141
- console.error("Error validating token:", error);
142
- }
143
- var res = await authClient.$fetch("/token");
140
+ var _res_data,
141
+ res = await authClient.$fetch("/token");
144
142
  if (res.error) {
145
143
  console.error(`Error fetching token: ${res.error.statusText}`);
146
144
  return;
147
145
  }
148
- var data = res.data;
149
- return data?.token;
146
+ return (_res_data = res.data) === null || _res_data === void 0 ? void 0 : _res_data.token;
150
147
  }
151
148
  var clearAuthClientToken = function () {
152
- keysStorage.remove();
153
- },
154
- getAuth = function () {
149
+ keysStorage.remove();
150
+ };
151
+ function clearAuthCookies() {
152
+ if (!(typeof document > "u")) {
153
+ var _iteratorNormalCompletion = !0,
154
+ _didIteratorError = !1,
155
+ _iteratorError = void 0;
156
+ try {
157
+ for (var _iterator = authCookieNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
158
+ var cookieName = _step.value;
159
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
160
+ var domain = window.location.hostname;
161
+ document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain}`, domain.startsWith(".") && (document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain.slice(1)}`);
162
+ }
163
+ } catch (err) {
164
+ _didIteratorError = !0, _iteratorError = err;
165
+ } finally {
166
+ try {
167
+ !_iteratorNormalCompletion && _iterator.return != null && _iterator.return();
168
+ } finally {
169
+ if (_didIteratorError) throw _iteratorError;
170
+ }
171
+ }
172
+ }
173
+ }
174
+ function clearAllAuth() {
175
+ clearAuthCookies(), clearState();
176
+ }
177
+ var getAuth = function () {
155
178
  var state = authState?.value || empty;
156
179
  return {
157
180
  ...state,
@@ -188,6 +211,7 @@ function createBetterAuthClient(options) {
188
211
  authClient: proxiedAuthClient,
189
212
  setAuthClientToken,
190
213
  clearAuthClientToken,
214
+ clearAllAuth,
191
215
  useAuth,
192
216
  getAuth,
193
217
  getValidToken,