---
title: "@xid-kit/electron"
description: "带主进程 PKCE 流程、contextBridge preload、操作系统 keychain token 存储以及 loopback 或自定义 scheme callback 策略的 Electron SDK。"
locale: "zh-Hans"
---

> Documentation Index
> Fetch the locale documentation index at: https://xid.dev/zh-hans/llms.txt
> Use this file to discover all available pages before exploring further.

# @xid-kit/electron

## 状态

包状态为 **当前包**。主进程应用、contextBridge preload 和渲染端 bridge 已实现。在真实生产基础设施上的 IdP 往返验证仍待人工核实。

## 入口点

| 入口 | 用途 |
| --- | --- |
| `@xid-kit/electron` | 默认导出：渲染器接口和类型 |
| `@xid-kit/electron/main` | 仅主进程：XidElectronApp |
| `@xid-kit/electron/renderer` | 渲染进程：getXidBridge、XidClient |
| `@xid-kit/electron/preload` | 暴露 window.xidBridge 的现成 preload 脚本 |

## 主进程配置

```ts
// main.ts
import { app, ipcMain } from 'electron'
import { XidElectronApp } from '@xid-kit/electron/main'

const xidApp = new XidElectronApp({
  issuer: 'https://xid.dev',
  clientId: 'client_abc123',
  // callbackStrategy: 'loopback' (default, RFC 8252 s.7.3) | 'custom-scheme'
})

app.whenReady().then(async () => {
  await xidApp.init(ipcMain)
  const win = new BrowserWindow({
webPreferences: {
  contextIsolation: true,
  preload: path.join(__dirname, 'preload.js'),
},
  })
  win.on('closed', () => xidApp.dispose(ipcMain))
})
```

## Preload 脚本

```ts
// preload.ts
import '@xid-kit/electron/preload'
// Exposes window.xidBridge with storage, signIn, signOut,
// getAccessToken, getSession, setTokenStorage
```

## 渲染进程

```ts
import { getXidBridge } from '@xid-kit/electron/renderer'

const bridge = getXidBridge()

// Opens system browser, waits for loopback callback, exchanges code.
const accessToken = await bridge.signIn()

// Get current access token (transparently refreshes if near expiry).
const token = await bridge.getAccessToken() // null when not signed in

// Get full session (accessToken + expiresAt in epoch seconds).
const session = await bridge.getSession()

// Sign out and clear tokens.
await bridge.signOut()
```

## 自定义 scheme（loopback 的替代方案）

```ts
// main.ts
import { app } from 'electron'
import { XidElectronApp } from '@xid-kit/electron/main'

app.setAsDefaultProtocolClient('myapp')

const xidApp = new XidElectronApp({
  issuer: 'https://xid.dev',
  clientId: 'client_abc123',
  callbackStrategy: 'custom-scheme',
  customScheme: 'myapp',  // redirect_uri = myapp://callback
})

xidApp.registerDeepLinkHandler(app)
```

## Token 存储

- 默认情况下，token 使用 `safeStorage.encryptString()`（操作系统 keychain）加密，并以二进制文件存储在 `app.getPath('userData')/xid-tokens/` 中。
- 如果 `safeStorage.isEncryptionAvailable()` 返回 `false`（无 keyring 的无界面 Linux），`setItem()` 会抛出带 code `encryption_unavailable` 的 `ElectronStorageError`，而不是静默写入明文。
- 在 `XidElectronMainOptions` 中用 `storageDir` 覆盖存储目录。

## 共享原生契约

| 方式 | 描述 |
| --- | --- |
| `signIn(options?)` | 打开系统浏览器，交换 code，存储 token |
| `signOut()` | 清除本地 token |
| `getAccessToken()` | 返回当前 token（接近过期时刷新）；已登出时返回 null |
| `getSession()` | 返回 accessToken 和 expiresAt，或 null |

Source: https://xid.dev/zh-hans/sdks/electron/index.mdx
