状态
Registry 状态:UNPUBLISHED。此 SDK 只能从仓库源码 checkout 安装;不要使用外部 package registry。
包状态为 当前包。主进程应用、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 脚本 |
主进程配置
// 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 脚本
// preload.ts
import '@xid-kit/electron/preload'
// Exposes window.xidBridge with storage, signIn, signOut,
// getAccessToken, getSession, setTokenStorage渲染进程
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 the current unexpired access token. Expiry requires a new sign-in.
const token = await bridge.getAccessToken() // null when signed out or expired
// Get the current unexpired session (accessToken + expiresAt in epoch seconds).
const session = await bridge.getSession()
// Clear local tokens. No refresh or revoke request is sent.
await bridge.signOut()自定义 scheme(loopback 的替代方案)
// 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()会抛出带 codeencryption_unavailable的ElectronStorageError,而不是静默写入明文。 - 在
XidElectronMainOptions中用storageDir覆盖存储目录。
共享原生契约
| 方式 | 描述 |
|---|---|
signIn(options?) |
打开系统浏览器,交换 code,存储 token |
signOut() |
清除本地 token |
getAccessToken() |
返回当前未过期的 access token,不执行 refresh;如果已过期,则清除本地状态并返回 null。在实现 DPoP 之前,SDK 会拒绝 offline_access。 |
getSession() |
返回当前未过期的 accessToken 和 expiresAt,或返回 null |