@bigio/better-auth-electron 1.0.3 → 1.0.4

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
@@ -2,13 +2,13 @@
2
2
 
3
3
  Based on my study of the official implementation code, I have decided on the following to-do list:
4
4
 
5
- **1. Architecture: The "Silent Handoff" (Stateless & Secure)**
5
+ **~~1. Architecture: The "Silent Handoff" (Stateless & Secure)~~**
6
6
 
7
- - [ ] **Server-Side Cookie Interception**: Modify `electron-server-plugin` to intercept the OAuth callback response.
8
- - _Action_: Strip the `Set-Cookie` header (specifically the session token) from the response to prevent overwriting the user's browser session.
9
- - _Goal_: Achieve strict physical isolation between Web Session and Electron Session.
7
+ - [done] ~~**Server-Side Cookie Interception**: Modify `electron-server-plugin` to intercept the OAuth callback response.~~
8
+ - ~~_Action_: Strip the `Set-Cookie` header (specifically the session token) from the response to prevent overwriting the user's browser session.~~
9
+ - ~~_Goal_: Achieve strict physical isolation between Web Session and Electron Session.~~
10
10
 
11
- - [ ] **Stateless OAuth Flow**: Ensure the OAuth flow relies solely on the encrypted `Ticket` mechanism, making the browser a purely stateless transport layer for Electron authentication.
11
+ - ~~**Stateless OAuth Flow**: Ensure the OAuth flow relies solely on the encrypted `Ticket` mechanism, making the browser a purely stateless transport layer for Electron authentication.~~
12
12
 
13
13
  **2. Security & Hardening**
14
14
 
@@ -28,7 +28,7 @@ Based on my study of the official implementation code, I have decided on the fol
28
28
  - _Feature_: Implement `authClient.bigio.signIn({ provider: 'github' })` wrapper.
29
29
  - _Implementation_: Utilize `window.open` (intercepted by Main) or IPC to trigger the flow, keeping the API consistent with the official web client style.
30
30
 
31
- - [ ] **Smart Web Handoff UI (Optional/Next)**: Update the web-side confirmation page to detect and display the currently logged-in web user, offering a "Continue as [User]" button for a seamless transition.
31
+ - [done] ~~**Smart Web Handoff UI (Optional/Next)**: Update the web-side confirmation page to detect and display the currently logged-in web user, offering a "Continue as [User]" button for a seamless transition.~~
32
32
 
33
33
  # @bigio/better-auth-electron
34
34
 
@@ -71,6 +71,14 @@ pnpm add better-auth electron react react-dom
71
71
 
72
72
  Initialize Better Auth with the `electronServerPlugin`. This handles the ticket exchange and verification logic on your backend.
73
73
 
74
+ #### The "Silent Handoff" Mechanism (Stateless & Secure)
75
+
76
+ This plugin implements a **Server-Side Cookie Interception** strategy to ensure strict isolation between the Web Session and the Electron Session.
77
+
78
+ - It intercepts OAuth callback responses specifically for Electron. It actively **removes the `Set-Cookie` header** (which contains the session token) before the response reaches the browser.
79
+ - This guarantees that the Electron login flow **does not overwrite or interfere** with the user's existing browser session.
80
+ - Authentication relies solely on a one-time encrypted Ticket. The browser acts as a purely **`stateless`** transport layer for Electron.
81
+
74
82
  ```typescript
75
83
  import { betterAuth } from 'better-auth'
76
84
  import { electronServerPlugin } from '@bigio/better-auth-electron/server'
@@ -130,7 +138,6 @@ const { windowInjection, whenReadyInjection } = mainInjection({
130
138
  PROVIDERS: ['github', 'google'],
131
139
  BETTER_AUTH_BASEURL: 'http://localhost:3002',
132
140
  FRONTEND_URL: 'http://localhost:3001/oauth',
133
- CONTENT_SECURITY_POLICY: '',
134
141
  /**
135
142
  * [Optional] Content Security Policy (CSP) Configuration
136
143
  * * Strategy: "All-or-Nothing"
@@ -195,7 +202,31 @@ export const authClient = createAuthClient({
195
202
  setLazyClient(authClient)
196
203
  ```
197
204
 
198
- ### 4. Electron Renderer / Login Page (`src/renderer/pages/login.tsx`)
205
+ ### 4. Electron Renderer/Web Client (`src/renderer/lib/auth-client.ts`)
206
+
207
+ This is the auth client running **inside your Electron app**. It listens for the custom protocol deep link to hydrate the session.
208
+
209
+ > **Suggestion:** set `credentials: 'include'` to ensure the session cookie generated by the secure protocol is correctly persisted.
210
+
211
+ ```typescript
212
+ import { createAuthClient } from 'better-auth/react'
213
+ import { electronRendererPlugin } from '@bigio/better-auth-electron/renderer'
214
+
215
+ export const authClient = createAuthClient({
216
+ baseURL: 'http://localhost:3002',
217
+ fetchOptions: {
218
+ // It ensures cookies are sent/received correctly in the custom scheme.
219
+ credentials: 'include',
220
+ },
221
+ plugins: [
222
+ electronRendererPlugin({
223
+ ELECTRON_SCHEME: 'bigio', // Must match Main process config
224
+ }),
225
+ ],
226
+ })
227
+ ```
228
+
229
+ ### 5. Electron Renderer / Login Page (`src/renderer/pages/login.tsx`)
199
230
 
200
231
  In your Electron renderer (the UI), use the helper options to construct the correct OAuth URL that opens in the system's default browser.
201
232
 
@@ -225,56 +256,65 @@ const ElectronLoginButton = ({ provider }: { provider: string }) => {
225
256
  }
226
257
  ```
227
258
 
228
- ### 5. Electron Renderer/Web Client (`src/renderer/lib/auth-client.ts`)
229
-
230
- This is the auth client running **inside your Electron app**. It listens for the custom protocol deep link to hydrate the session.
231
-
232
- > **Suggestion:** set `credentials: 'include'` to ensure the session cookie generated by the secure protocol is correctly persisted.
259
+ ### 6. Web/App Component Usage (`src/web/components/user-session.tsx`)
233
260
 
234
- ```typescript
235
- import { createAuthClient } from 'better-auth/react'
236
- import { electronRendererPlugin } from '@bigio/better-auth-electron/renderer'
261
+ The `useElectronOAuthSession` hook is the core of the "Handoff" experience. It manages the synchronization between the web authentication state and the Electron application.
237
262
 
238
- export const authClient = createAuthClient({
239
- baseURL: 'http://localhost:3002',
240
- fetchOptions: {
241
- // It ensures cookies are sent/received correctly in the custom scheme.
242
- credentials: 'include',
243
- },
244
- plugins: [
245
- electronRendererPlugin({
246
- ELECTRON_SCHEME: 'bigio', // Must match Main process config
247
- }),
248
- ],
249
- })
250
- ```
263
+ #### Component Implementation
251
264
 
252
- ### 6. Web/App Component Usage (`src/web/components/user-session.tsx`)
265
+ The hook provides reactive states to manage the UI. Most importantly, the 'pending' state serves as a "Session Detected" signal.
253
266
 
254
- The `useElectronOAuthSession` hook is the heart of the "Handoff" experience. It listens for the deep link callback and automatically verifies the session.
267
+ To resolve this state, you use the `setFastLogin` function. Calling this function immediately updates the oauthStatus and triggers the next step in the authentication flow.
255
268
 
256
- ```typescript
269
+ ```tsx
270
+ import { useEffect } from 'react'
257
271
  import { authClient } from '@/web/client'
258
272
 
259
273
  export function UserSessionStatus() {
260
274
  const {
261
- data: useSessionData,
275
+ data: sessionData,
262
276
  error,
263
- isPending,
264
- isRefetching,
265
- refetch,
266
- // // The current status of the handoff process on the client side
267
- // (e.g., 'idle' | 'succeed' | 'failed')
268
- oauthMessage
277
+ isPending, // Initial loading state
278
+
279
+ // Status enum: 'idle' | 'pending' | 'connecting' | 'succeed' | 'failed'
280
+ // 'pending': CRITICAL state. It confirms a valid session ALREADY exists
281
+ // and the system is pausing to wait for the user's decision.
282
+ oauthStatus,
283
+ oauthError,
284
+
285
+ // Action to control the flow:
286
+ // setFastLogin(true) = Fast Login (Use current session)
287
+ // setFastLogin(false) = Switch Account (Ignore current session)
288
+ setFastLogin,
269
289
  } = authClient.bigio.useElectronOAuthSession()
270
290
 
271
- if (isPending) return <div>Loading session... {oauthMessage}</div>
272
- if (error) return <div>Error: {error.message}</div>
291
+ /**
292
+ * Optional: Force Logic (Auto-decision)
293
+ * If you want to skip the user choice UI:
294
+ */
295
+ useEffect(() => {
296
+ setFastLogin(true) // Force Fast Login immediately
297
+ // OR
298
+ setFastLogin(false) // Force Switch Account immediately
299
+ }, [])
273
300
 
301
+ /**
302
+ * Optional: User-decision
303
+ * If you want to let the user choice:
304
+ */
274
305
  return (
275
306
  <div>
276
- <h1>Welcome, {useSessionData?.user.name}</h1>
277
- <p>Status: {oauthMessage || 'Idle'}</p>
307
+ {/* The 'pending' status indicates a session collision/detection.
308
+ We present the choice to the user here.
309
+ */}
310
+ {oauthStatus === 'pending' ? (
311
+ <>
312
+ {/* Option: Ignore current session and re-login */}
313
+ <button onClick={() => setFastLogin(false)}>Switch Account</button>
314
+ {/* Option: Use current session for Electron */}
315
+ <button onClick={() => setFastLogin(true)}>Fast Login</button>
316
+ </>
317
+ ) : null}
278
318
  </div>
279
319
  )
280
320
  }
package/dist/main.js CHANGED
@@ -3047,7 +3047,6 @@ var mainInjection = (options) => {
3047
3047
  const responseHeaders = {
3048
3048
  ...details.responseHeaders,
3049
3049
  "Content-Security-Policy": [CONTENT_SECURITY_POLICY ?? fallbackCSP]
3050
- // 注入!
3051
3050
  };
3052
3051
  callback({
3053
3052
  responseHeaders,