@bigio/better-auth-electron 1.0.3 → 1.0.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.
package/README.md CHANGED
@@ -1,14 +1,92 @@
1
- ## I'm currently studying the official implementation; the documentation is still rough but will be improved soon. I'm eager and looking forward to exchanging ideas with everyone.
1
+ # @bigio/better-auth-electron
2
+
3
+ This plugin establishes a secure, **event-driven** authentication bridge between Electron and Better Auth. It treats the system browser strictly as a **stateless transport layer**, utilizing **AES-encrypted tickets** and **PKCE verification** to perform session handoff without persisting web cookies in the desktop environment.
4
+
5
+ The renderer implementation abandons traditional redirect handling in favor of an IPC-based subscription model (`onDeepLink*`). It features a built-in **cold-start buffer** to guarantee token capture even if the deep link triggers the application before the UI is fully mounted. The API surface is designed to mirror the official Better Auth client patterns, ensuring strict typing and zero-friction integration.
6
+
7
+ ### Key Architecture
8
+
9
+ - **Stateless Web Handoff**: The browser authenticates via OAuth but does not share the session with Electron. It passes an encrypted, time-limited ticket back to the desktop app.
10
+ - **Security**: Full PKCE flow (Proof Key for Code Exchange) with verified challenges and AES-encrypted exchange tickets.
11
+ - **Event-Driven Renderer**: No page reloads or router redirects. Listen for `onDeepLinkSuccess`, `onDeepLinkNewUser`, or `onDeepLinkFailed` directly within your React/Vue components.
12
+ - **Cold Start Support**: Includes an internal IPC buffer to cache deep link events that occur during the application boot phase, ensuring no authentication intent is lost while the renderer initializes.
13
+ - **API Parity**: Extends the `authClient` with a `bigio` namespace that mimics standard Better Auth methods (e.g., `signInSocial`).
14
+ - **Native Secure Context & Origin Fix:** Leverages `protocol.registerSchemesAsPrivileged` to treat your custom scheme as a secure context. This solves the infamous `Origin` header mismatch and enables `SameSite` cookies to work natively without hacks.
15
+
16
+ #### _I'm currently studying the official implementation; the documentation is still rough but will be improved soon. I'm eager and looking forward to exchanging ideas with everyone._
17
+
18
+ # Authentication Flow
19
+
20
+ The following diagram illustrates the complete OAuth authorization and session handoff process, including the interaction with external **OAuth Providers** (e.g., GitHub, Google):
21
+
22
+ ```mermaid
23
+ sequenceDiagram
24
+ participant User as User
25
+ participant E_R as Electron Renderer
26
+ participant E_M as Electron Main
27
+ participant Browser as External Browser (Web Frontend)
28
+ participant Server as Auth Server (Better Auth)
29
+ participant Provider as OAuth Provider (GitHub/Google)
30
+
31
+ Note over E_R, E_M: 1. Initialization & Startup
32
+ E_R->>E_M: Send App Mounted Signal
33
+ User->>E_R: Click Login
34
+ E_R->>E_R: Click Login (window.open)
35
+ E_M->>E_M: Intercept Request, Generate PKCE Verifier
36
+ E_M->>Browser: Open External Browser (with Challenge)
37
+
38
+ Note over Browser, Provider: 2. Web Handoff Decision & OAuth Flow
39
+ alt Session Exists
40
+ Browser->>Browser: Detect Active Session
41
+ Browser->>User: Show "Continue as [User]" or "Switch Account"
42
+ alt User selects "Fast Login"
43
+ User->>Browser: Click "Continue as [User]"
44
+ Browser->>Server: Request Fast Ticket (POST /fast-ticket)
45
+ Server->>Server: Generate Encrypted Ticket
46
+ Server-->>Browser: Return Redirect URL (bigio://...)
47
+ else User selects "Switch Account"
48
+ User->>Browser: Click "Switch Account"
49
+ Browser->>Server: Initiate OAuth (signIn.social)
50
+ Server->>Provider: Redirect to Provider Login
51
+ Provider->>User: Prompt for Credentials
52
+ User->>Provider: Authorize App
53
+ Provider-->>Server: Callback with Code/Token
54
+ Note right of Server: Stateless: Set-Cookie is intercepted/removed
55
+ Server->>Server: Auth Success, Generate Encrypted Ticket
56
+ Server-->>Browser: Redirect to bigio://callback?ticket=...
57
+ end
58
+ else No Session
59
+ User->>Browser: Select Provider
60
+ Browser->>Server: Initiate OAuth (signIn.social)
61
+ Server->>Provider: Redirect to Provider Login
62
+ Provider->>User: Prompt for Credentials
63
+ User->>Provider: Authorize App
64
+ Provider-->>Server: Callback with Code/Token
65
+ Note right of Server: Stateless: Set-Cookie is intercepted/removed
66
+ Server->>Server: Auth Success, Generate Encrypted Ticket
67
+ Server-->>Browser: Redirect to bigio://callback?ticket=...
68
+ end
69
+
70
+ Note over Browser, E_R: 3. Session Handoff
71
+ Browser->>E_M: Trigger Deep Link (Custom Protocol)
72
+ E_M->>E_R: Send Ticket & Verifier via IPC
73
+ E_R->>E_R: Verify PKCE Challenge
74
+ E_R->>Server: POST /exchange-ticket (Ticket + Verifier)
75
+ Server->>Server: Decrypt Ticket, Verify PKCE
76
+ Server->>Server: Create Electron-specific Session
77
+ Server-->>E_R: Return Session Cookie (SameSite=None)
78
+ E_R->>E_R: Login Success, Refresh UI
79
+ ```
2
80
 
3
81
  Based on my study of the official implementation code, I have decided on the following to-do list:
4
82
 
5
- **1. Architecture: The "Silent Handoff" (Stateless & Secure)**
83
+ **~~1. Architecture: The "Silent Handoff" (Stateless & Secure)~~**
6
84
 
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.
85
+ - [done] ~~**Server-Side Cookie Interception**: Modify `electron-server-plugin` to intercept the OAuth callback response.~~
86
+ - ~~_Action_: Strip the `Set-Cookie` header (specifically the session token) from the response to prevent overwriting the user's browser session.~~
87
+ - ~~_Goal_: Achieve strict physical isolation between Web Session and Electron Session.~~
10
88
 
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.
89
+ - ~~**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
90
 
13
91
  **2. Security & Hardening**
14
92
 
@@ -24,36 +102,13 @@ Based on my study of the official implementation code, I have decided on the fol
24
102
 
25
103
  **3. Developer Experience (DX) & API**
26
104
 
27
- - [ ] **Enhanced Renderer API**: Refactor `getActions` to introduce a dedicated `authClient.bigio` namespace.
28
- - _Feature_: Implement `authClient.bigio.signIn({ provider: 'github' })` wrapper.
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
-
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.
32
-
33
- # @bigio/better-auth-electron
34
-
35
- > **Work In Progress:** This library is actively being developed. Detailed documentation and architecture diagrams are coming soon.
36
-
37
- **A type-safe, IPC-Event based Better Auth integration for Electron.**
105
+ - [done] ~~**Enhanced Renderer API**: Refactor `getActions` to introduce a dedicated `authClient.bigio` namespace.~~
106
+ - ~~_Feature_: Implement `authClient.bigio.signIn({ provider: 'github' })` wrapper.~~
107
+ - ~~_Implementation_: Utilize `window.open` (intercepted by Main) or IPC to trigger the flow, keeping the API consistent with the official web client style.~~
38
108
 
39
- Designed for production-grade applications, this library provides a secure, "batteries-included" solution to integrate [Better Auth](https://www.better-auth.com) into Electron apps without the headache of writing manual IPC bridges or handling complex OAuth window flows.
109
+ - [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.~~
40
110
 
41
- ## Features
42
-
43
- - ** Native Secure Context & Origin Fix:**
44
- Leverages `protocol.registerSchemesAsPrivileged` to treat your custom scheme as a secure context. This solves the infamous `Origin` header mismatch and enables `SameSite` cookies to work natively without hacks.
45
-
46
- - ** Secure PKCE Flow:**
47
- Implements the standard **Proof Key for Code Exchange** protocol out-of-the-box. Ensures enterprise-grade security for your OAuth exchanges without exposing secrets.
48
-
49
- - ** Preact SSR Coming soon:**
50
- Includes a dedicated, lightweight Preact entry point optimized for Server-Side Rendering (SSR) in login windows.
51
- _(React 19 supported. Vue/Svelte support coming soon!)_
52
-
53
- - ** Zero-IPC Session Handoff:**
54
- Uses secure custom protocol deep links to transfer authentication states. Full TypeScript inference via Better Auth plugins — **no fragile IPC bridges** or manual message handling required.
55
-
56
- ## Installation
111
+ # Installation
57
112
 
58
113
  ```bash
59
114
  pnpm add @bigio/better-auth-electron
@@ -65,12 +120,20 @@ Ensure peer dependencies are installed:(more framework support coming soon...)
65
120
  pnpm add better-auth electron react react-dom
66
121
  ```
67
122
 
68
- ## Quick Start
123
+ # Quick Start
69
124
 
70
125
  ### 1. Server Setup (`src/lib/auth.ts`)
71
126
 
72
127
  Initialize Better Auth with the `electronServerPlugin`. This handles the ticket exchange and verification logic on your backend.
73
128
 
129
+ #### The "Silent Handoff" Mechanism (Stateless & Secure)
130
+
131
+ This plugin implements a **Server-Side Cookie Interception** strategy to ensure strict isolation between the Web Session and the Electron Session.
132
+
133
+ - 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.
134
+ - This guarantees that the Electron login flow **does not overwrite or interfere** with the user's existing browser session.
135
+ - Authentication relies solely on a one-time encrypted Ticket. The browser acts as a purely **`stateless`** transport layer for Electron.
136
+
74
137
  ```typescript
75
138
  import { betterAuth } from 'better-auth'
76
139
  import { electronServerPlugin } from '@bigio/better-auth-electron/server'
@@ -130,7 +193,6 @@ const { windowInjection, whenReadyInjection } = mainInjection({
130
193
  PROVIDERS: ['github', 'google'],
131
194
  BETTER_AUTH_BASEURL: 'http://localhost:3002',
132
195
  FRONTEND_URL: 'http://localhost:3001/oauth',
133
- CONTENT_SECURITY_POLICY: '',
134
196
  /**
135
197
  * [Optional] Content Security Policy (CSP) Configuration
136
198
  * * Strategy: "All-or-Nothing"
@@ -195,37 +257,7 @@ export const authClient = createAuthClient({
195
257
  setLazyClient(authClient)
196
258
  ```
197
259
 
198
- ### 4. Electron Renderer / Login Page (`src/renderer/pages/login.tsx`)
199
-
200
- 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
-
202
- ```typescript
203
- import type { ElectronButtonOptions } from '@bigio/better-auth-electron/options'
204
- import { defaultButtonOptions } from '@bigio/better-auth-electron/options'
205
-
206
- // Merge default options with any custom overrides
207
- const config: ElectronButtonOptions = { ...defaultButtonOptions }
208
- const { FRONTEND_URL, PROVIDER_NAME_IN_URL } = config
209
-
210
- const ElectronLoginButton = ({ provider }: { provider: string }) => {
211
- const handleOpen = () => {
212
- // Construct the auth URL
213
- const targetUrl = `${FRONTEND_URL}?${PROVIDER_NAME_IN_URL}=${provider}`
214
-
215
- // Open in external browser (e.g., Chrome/Safari) to start the flow
216
- window.open(targetUrl, '_blank')
217
- console.log('Opening External Browser for OAuth...')
218
- }
219
-
220
- return (
221
- <button onClick={handleOpen}>
222
- Sign in with {provider}
223
- </button>
224
- )
225
- }
226
- ```
227
-
228
- ### 5. Electron Renderer/Web Client (`src/renderer/lib/auth-client.ts`)
260
+ ### 4. Electron Renderer/Web Client (`src/renderer/lib/auth-client.ts`)
229
261
 
230
262
  This is the auth client running **inside your Electron app**. It listens for the custom protocol deep link to hydrate the session.
231
263
 
@@ -249,32 +281,183 @@ export const authClient = createAuthClient({
249
281
  })
250
282
  ```
251
283
 
284
+ ### 5. Electron Renderer Integration (New API)
285
+
286
+ I have refactored the client-side integration to closely mirror the official Better Auth API structure, while adapting it for the specific constraints of the Electron environment (IPC & Deep Linking).
287
+
288
+ ### Key Features
289
+
290
+ - **Official API Parity:** Uses a syntax similar to `authClient.signIn.social`.
291
+ - **Callback Functions over URLs:** Instead of handling redirects, we use event subscriptions (`onDeepLinkSuccess`, `onDeepLinkNewUser`) to handle the authentication result.
292
+ - **Cold Start Support:** The plugin includes an internal buffer. If the application is opened via a Deep Link before the UI is fully mounted, the plugin caches the session data and triggers the callback immediately upon registration.
293
+
294
+ ### Implementation
295
+
296
+ In your Electron renderer (e.g., `src/renderer/pages/login.tsx`), use the `bigio` namespace exposed by the client plugin.
297
+
298
+ #### 1. Triggering the Sign-In
299
+
300
+ Use `signInSocial` to initiate the flow. This handles the construction of the OAuth URL, serialization of scopes/parameters, and automatically opens the system default browser.
301
+
302
+ **Note on Constraints:**
303
+
304
+ 1. **`disableRedirect`** is forced to `false`. The flow _must_ redirect to the deep link scheme to trigger the Electron app.
305
+ 2. **`additionalData`** is **JSON serialized and encoded into the URL**. Do not pass sensitive data or large objects, as they may hit browser URL length limits.
306
+
307
+ ```tsx
308
+ import { authClient } from '@/lib/auth-client' // Your initialized client
309
+
310
+ // ... inside your component
311
+ ;<button
312
+ onClick={async () => {
313
+ await authClient.bigio.signInSocial({
314
+ // [Required] The provider key (e.g., 'github', 'google')
315
+ provider: 'github',
316
+
317
+ // [Optional] Array of OAuth scopes
318
+ scopes: ['repo', 'user'],
319
+
320
+ // [Optional] Object passed to the backend (JSON serialized via URL)
321
+ // Warning: Keep this payload small to avoid URL length issues.
322
+ additionalData: {
323
+ theme: 'dark',
324
+ ref_source: 'desktop_app',
325
+ },
326
+
327
+ // [Optional] Hint for the provider (e.g., email address)
328
+ loginHint: 'user@example.com',
329
+
330
+ // [Optional] Force a sign-up screen instead of sign-in
331
+ requestSignUp: false,
332
+ })
333
+ }}>
334
+ Sign in with GitHub
335
+ </button>
336
+ ```
337
+
338
+ #### 2. Handling the Callback (Deep Link)
339
+
340
+ Instead of a page redirect, we listen for IPC completion events. You **must** register listeners for success, failure, and (optionally) new user creation.
341
+
342
+ These functions return an **unsubscribe** handler. You are responsible for cleaning this up to prevent memory leaks or double-firing events.
343
+
344
+ ```tsx
345
+ import { useEffect } from 'react'
346
+ import { useNavigate } from 'react-router-dom'
347
+ import { authClient } from '@/lib/auth-client'
348
+
349
+ export default function LoginPage() {
350
+ const navigate = useNavigate()
351
+
352
+ useEffect(() => {
353
+ // 1. Handle Successful Login (Returning User)
354
+ const unsubscribeSuccess = authClient.bigio.onDeepLinkSuccess(async (data) => {
355
+ console.log('Login Successful:', data)
356
+ // data contains { user, session }
357
+ navigate('/dashboard')
358
+ return true
359
+ })
360
+
361
+ // 2. Handle New User Registration (First Time Login)
362
+ // If not provided, 'onDeepLinkSuccess' might be triggered depending on backend config,
363
+ // but it is recommended to handle new users explicitly if you have an onboarding flow.
364
+ const unsubscribeNewUser = authClient.bigio.onDeepLinkNewUser(async (data) => {
365
+ console.log('New User Registered:', data)
366
+ // data contains { user, session }
367
+ navigate('/onboarding')
368
+ return true
369
+ })
370
+
371
+ // 3. Handle Errors (Network issues, User denied access, Invalid State)
372
+ const unsubscribeError = authClient.bigio.onDeepLinkFailed(async (error) => {
373
+ console.error('Authentication Failed:', error)
374
+ // Show toast or error message
375
+ })
376
+
377
+ // Cleanup: Essential for React's StrictMode and component unmounting
378
+ return () => {
379
+ unsubscribeSuccess()
380
+ unsubscribeNewUser()
381
+ unsubscribeError()
382
+ }
383
+ }, [])
384
+
385
+ return (
386
+ // ... your JSX
387
+ )
388
+ }
389
+
390
+ ```
391
+
392
+ ### API Reference: `signInSocial`
393
+
394
+ | Parameter | Type | Description |
395
+ | ---------------- | ------------------------- | ------------------------------------------------------------------ |
396
+ | `provider` | `string` | **Required.** The key of the provider (e.g., `github`). |
397
+ | `scopes` | `string[]` | **Optional.** Additional OAuth scopes to request. |
398
+ | `additionalData` | `Record<string, unknown>` | **Optional.** Metadata sent to the backend. **Serialized to URL.** |
399
+ | `loginHint` | `string` | **Optional.** Passes a hint (usually email) to the provider. |
400
+ | `requestSignUp` | `boolean` | **Optional.** Hints the provider to show the registration page. |
401
+
252
402
  ### 6. Web/App Component Usage (`src/web/components/user-session.tsx`)
253
403
 
254
- The `useElectronOAuthSession` hook is the heart of the "Handoff" experience. It listens for the deep link callback and automatically verifies the session.
404
+ The `useElectronOAuthSession` hook is the core of the "Handoff" experience. It manages the synchronization between the web authentication state and the Electron application.
255
405
 
256
- ```typescript
406
+ #### Component Implementation
407
+
408
+ The hook provides reactive states to manage the UI. Most importantly, the 'pending' state serves as a "Session Detected" signal.
409
+
410
+ 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.
411
+
412
+ ```tsx
413
+ import { useEffect } from 'react'
257
414
  import { authClient } from '@/web/client'
258
415
 
259
416
  export function UserSessionStatus() {
260
417
  const {
261
- data: useSessionData,
418
+ data: sessionData,
262
419
  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
420
+ isPending, // Initial loading state
421
+
422
+ // Status enum: 'idle' | 'pending' | 'connecting' | 'succeed' | 'failed'
423
+ // 'pending': CRITICAL state. It confirms a valid session ALREADY exists
424
+ // and the system is pausing to wait for the user's decision.
425
+ oauthStatus,
426
+ oauthError,
427
+
428
+ // Action to control the flow:
429
+ // setFastLogin(true) = Fast Login (Use current session)
430
+ // setFastLogin(false) = Switch Account (Ignore current session)
431
+ setFastLogin,
269
432
  } = authClient.bigio.useElectronOAuthSession()
270
433
 
271
- if (isPending) return <div>Loading session... {oauthMessage}</div>
272
- if (error) return <div>Error: {error.message}</div>
434
+ /**
435
+ * Optional: Force Logic (Auto-decision)
436
+ * If you want to skip the user choice UI:
437
+ */
438
+ useEffect(() => {
439
+ setFastLogin(true) // Force Fast Login immediately
440
+ // OR
441
+ setFastLogin(false) // Force Switch Account immediately
442
+ }, [])
273
443
 
444
+ /**
445
+ * Optional: User-decision
446
+ * If you want to let the user choice:
447
+ */
274
448
  return (
275
449
  <div>
276
- <h1>Welcome, {useSessionData?.user.name}</h1>
277
- <p>Status: {oauthMessage || 'Idle'}</p>
450
+ {/* The 'pending' status indicates a session collision/detection.
451
+ We present the choice to the user here.
452
+ */}
453
+ {oauthStatus === 'pending' ? (
454
+ <>
455
+ {/* Option: Ignore current session and re-login */}
456
+ <button onClick={() => setFastLogin(false)}>Switch Account</button>
457
+ {/* Option: Use current session for Electron */}
458
+ <button onClick={() => setFastLogin(true)}>Fast Login</button>
459
+ </>
460
+ ) : null}
278
461
  </div>
279
462
  )
280
463
  }
package/dist/main.js CHANGED
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  import process2 from 'process';
4
4
  import { pathToFileURL } from 'url';
5
5
  import { app, protocol, ipcMain, shell, session, net } from 'electron';
6
- import z2 from 'zod';
6
+ import z, { boolean } from 'zod';
7
7
 
8
8
  var __create = Object.create;
9
9
  var __defProp = Object.defineProperty;
@@ -2236,7 +2236,6 @@ var defaultMainPluginOptions = {
2236
2236
  isOAuth: true,
2237
2237
  BETTER_AUTH_BASEURL: "http://localhost:3002",
2238
2238
  ELECTRON_APP_NAME: "bigio-electron-demo",
2239
- PROVIDERS: ["github", "google"],
2240
2239
  ELECTRON_APP_HOST: "app-renderer",
2241
2240
  ELECTRON_SCHEME: "bigio",
2242
2241
  ELECTRON_RENDERER_PATH: "out/renderer",
@@ -2245,11 +2244,10 @@ var defaultMainPluginOptions = {
2245
2244
  CLEAR_COOKIES_EVENT_NAME: "clear-Cookies",
2246
2245
  GET_COOKIES_EVENT_NAME: "get-Cookies",
2247
2246
  ELECTRON_VERIFIER_LENGTH: 32,
2248
- FRONTEND_URL: "http://localhost:3002/oauth",
2247
+ FRONTEND_URL: "http://localhost:3001/oauth",
2249
2248
  WEB_OAUTH_SIGNIN_CALLBACK_PATHNAME: "electron-handoff",
2250
2249
  SCHEME_NAME_IN_URL: "scheme",
2251
- PROVIDER_NAME_IN_URL: "provider",
2252
- CHALLENGE_NAME_IN_URL: "electron_challenge",
2250
+ CHALLENGE_NAME_IN_URL: "electron-challenge",
2253
2251
  CALLBACK_PATHNAME_IN_URL: "callbackpath",
2254
2252
  OLD_SCHOOL_ONBEFORE_WAY: false,
2255
2253
  ELECTRON_CALLBACK_HOST_PATH: "better-auth-callback",
@@ -2669,6 +2667,7 @@ function safeTry(func, errorMessage) {
2669
2667
  var crypto = globalThis.crypto;
2670
2668
  var ALGO_SHA = "SHA-256";
2671
2669
  var GLOBAL_ENCODER = new TextEncoder();
2670
+ new TextDecoder();
2672
2671
  function encode64(buffer) {
2673
2672
  const checkBuffer = okOr(buffer, {
2674
2673
  msg: "Invalid buffer input for toBase64Url",
@@ -2715,11 +2714,17 @@ async function pkceGenerateChallenge(verifier) {
2715
2714
  });
2716
2715
  return encode64(hashBuffer);
2717
2716
  }
2717
+ z.object({
2718
+ scopes: z.array(z.string()).optional(),
2719
+ loginHint: z.string().optional(),
2720
+ additionalData: z.record(z.string(), z.any()).optional(),
2721
+ requestSignUp: boolean().optional()
2722
+ });
2718
2723
 
2719
2724
  // src/main/electron-main-plugin.ts
2720
2725
  import_main.default.initialize();
2721
2726
  var isInitializedAtom = atom(false);
2722
- var deepLinkUrlAtom = atom(null);
2727
+ var deepLinkUrlTempAtom = atom(null);
2723
2728
  var browserWindowAtom = atom(null);
2724
2729
  var getMainWindow = () => {
2725
2730
  const mainWindow = browserWindowAtom.get();
@@ -2757,9 +2762,9 @@ var popUpWindow = (win) => {
2757
2762
  }
2758
2763
  win.focus();
2759
2764
  };
2760
- var verifierZod = z2.object({
2761
- verifier: z2.string(),
2762
- expiresAt: z2.number()
2765
+ var verifierZod = z.object({
2766
+ verifier: z.string(),
2767
+ expiresAt: z.number()
2763
2768
  });
2764
2769
  var mainInjection = (options) => {
2765
2770
  if (isInitializedAtom.get()) {
@@ -2786,11 +2791,9 @@ var mainInjection = (options) => {
2786
2791
  FRONTEND_URL,
2787
2792
  CHALLENGE_NAME_IN_URL,
2788
2793
  SCHEME_NAME_IN_URL,
2789
- PROVIDER_NAME_IN_URL,
2790
2794
  ELECTRON_APP_HOST,
2791
2795
  ELECTRON_RENDERER_PATH,
2792
2796
  ELECTRON_VERIFIER_FILE_NAME,
2793
- PROVIDERS,
2794
2797
  ELECTRON_APP_NAME,
2795
2798
  OLD_SCHOOL_ONBEFORE_WAY,
2796
2799
  CONTENT_SECURITY_POLICY
@@ -2894,9 +2897,9 @@ var mainInjection = (options) => {
2894
2897
  deepLinkURL,
2895
2898
  verifier: getElectronVerifier()
2896
2899
  });
2897
- deepLinkUrlAtom.set(null);
2900
+ deepLinkUrlTempAtom.set(null);
2898
2901
  } else {
2899
- deepLinkUrlAtom.set(deepLinkURL);
2902
+ deepLinkUrlTempAtom.set(deepLinkURL);
2900
2903
  }
2901
2904
  };
2902
2905
  app.on("open-url", (event, deepLinkURL) => {
@@ -2910,7 +2913,7 @@ var mainInjection = (options) => {
2910
2913
  if (process2.platform === "win32") {
2911
2914
  const coldStartUrl = process2.argv.find((arg) => arg.startsWith(`${ELECTRON_SCHEME}://`));
2912
2915
  if (coldStartUrl) {
2913
- deepLinkUrlAtom.set(coldStartUrl);
2916
+ deepLinkUrlTempAtom.set(coldStartUrl);
2914
2917
  }
2915
2918
  }
2916
2919
  app.on("second-instance", (_event, commandLine, workingDirectory) => {
@@ -2921,13 +2924,13 @@ var mainInjection = (options) => {
2921
2924
  });
2922
2925
  ipcMain.removeAllListeners(APP_MOUNTED_EVENT_NAME);
2923
2926
  ipcMain.on(APP_MOUNTED_EVENT_NAME, (event) => {
2924
- const deepLinkURL = deepLinkUrlAtom.get();
2927
+ const deepLinkURL = deepLinkUrlTempAtom.get();
2925
2928
  if (deepLinkURL) {
2926
2929
  event.sender.send(DEEPLINK_EVENT_NAME, {
2927
2930
  deepLinkURL,
2928
2931
  verifier: getElectronVerifier()
2929
2932
  });
2930
- deepLinkUrlAtom.set(null);
2933
+ deepLinkUrlTempAtom.set(null);
2931
2934
  }
2932
2935
  });
2933
2936
  ipcMain.removeHandler(GET_COOKIES_EVENT_NAME);
@@ -2977,25 +2980,6 @@ var mainInjection = (options) => {
2977
2980
  true
2978
2981
  );
2979
2982
  const url = new URL(targetUrl);
2980
- const provider = okOr(
2981
- url.searchParams.get(PROVIDER_NAME_IN_URL),
2982
- new BigIOError("No provider", {
2983
- bigioErrorStack: [
2984
- {
2985
- ctx: targetUrl
2986
- }
2987
- ]
2988
- })
2989
- );
2990
- if (!PROVIDERS.includes(provider)) {
2991
- throw new BigIOError("Error Provider", {
2992
- bigioErrorStack: [
2993
- {
2994
- ctx: targetUrl
2995
- }
2996
- ]
2997
- });
2998
- }
2999
2983
  url.searchParams.set(CHALLENGE_NAME_IN_URL, challenge);
3000
2984
  url.searchParams.set(SCHEME_NAME_IN_URL, ELECTRON_SCHEME);
3001
2985
  shell.openExternal(url.toString());
@@ -3047,7 +3031,6 @@ var mainInjection = (options) => {
3047
3031
  const responseHeaders = {
3048
3032
  ...details.responseHeaders,
3049
3033
  "Content-Security-Policy": [CONTENT_SECURITY_POLICY ?? fallbackCSP]
3050
- // 注入!
3051
3034
  };
3052
3035
  callback({
3053
3036
  responseHeaders,