Skip to content

@xid-kit/electron

Electron SDK with main process PKCE flow, contextBridge preload, OS keychain token storage, and loopback or custom-scheme callback strategies.

Status

Package status is Current package. Main process app, contextBridge preload, and renderer-side bridge are implemented. A real IdP round-trip on production infrastructure is still pending manual verification.

Entry points

Entry Purpose
@xid-kit/electron Default export: renderer surface and types
@xid-kit/electron/main Main process only: XidElectronApp
@xid-kit/electron/renderer Renderer process: getXidBridge, XidClient
@xid-kit/electron/preload Ready-made preload script that exposes window.xidBridge

Main process setup

// 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 script

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

Renderer process

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()

Custom scheme (alternative to 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 storage

  • Tokens are encrypted with safeStorage.encryptString() (OS keychain) and stored as binary files in app.getPath('userData')/xid-tokens/ by default.
  • If safeStorage.isEncryptionAvailable() returns false (headless Linux without a keyring), setItem() throws ElectronStorageError with code encryption_unavailable rather than writing plaintext silently.
  • Override the storage directory with storageDir in XidElectronMainOptions.

Shared native contract

Method Description
signIn(options?) Opens system browser, exchanges code, stores tokens
signOut() Clears local tokens
getAccessToken() Returns current token (refreshes if near expiry); null if signed out
getSession() Returns accessToken and expiresAt, or null
Navigation

Type to search...

Use arrow keys to navigateEnter to selectEscape to close