@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 +83 -43
- package/dist/main.js +0 -1
- package/dist/main.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/server.js +5 -4
- package/dist/server.js.map +1 -1
- package/dist/web.d.ts +7 -11
- package/dist/web.js +51 -115
- package/dist/web.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
5
|
+
**~~1. Architecture: The "Silent Handoff" (Stateless & Secure)~~**
|
|
6
6
|
|
|
7
|
-
- [
|
|
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
|
-
-
|
|
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
|
-
- [
|
|
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
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
265
|
+
The hook provides reactive states to manage the UI. Most importantly, the 'pending' state serves as a "Session Detected" signal.
|
|
253
266
|
|
|
254
|
-
|
|
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
|
-
```
|
|
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:
|
|
275
|
+
data: sessionData,
|
|
262
276
|
error,
|
|
263
|
-
isPending,
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
|
|
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
|
-
|
|
272
|
-
|
|
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
|
-
|
|
277
|
-
|
|
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