Add Chrome extension cookie bridge for session import
Users logged into Alta in Chrome can now send their session cookie to the running Electron app via a local HTTP server on port 18247, eliminating the need for re-authentication. - main.js: HTTP cookie server with CORS, token, domain validation - preload.js: onExtensionCookie push-pattern IPC bridge - renderer.js: handleExtensionCookie sets session, fetches devices - chrome-extension/: Manifest V3 extension with popup UI - CLAUDE.md: updated architecture docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
Alta Video Camera Proxy — an Electron desktop app that authenticates with Avigilon Alta Video deployments, discovers cameras, and launches external proxy executables (`aware-cam-proxy-win.exe`, `aware-cam-proxy.exe`) to establish camera connections. Windows-only due to the proxy executables.
|
||||
Alta Proxy Tool (APT) — an Electron desktop app that authenticates with Avigilon Alta Video deployments, discovers cameras, and launches external proxy executables (`aware-cam-proxy-win.exe`, `aware-cam-proxy.exe`) to establish camera connections. Windows-only due to the proxy executables.
|
||||
|
||||
## Repository
|
||||
|
||||
- **GitHub**: https://github.com/PageZ948/Alta-Proxy-Tool (private)
|
||||
- **Branch**: master
|
||||
- **Git identity**: Zac <zpage948@gmail.com> (repo-local config)
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -19,26 +25,43 @@ No test framework is configured. No linter is configured.
|
||||
|
||||
## Architecture
|
||||
|
||||
This is a vanilla Electron app (no React/Vue/framework). Four files form the entire application:
|
||||
This is a vanilla Electron app (no React/Vue/framework). Core files:
|
||||
|
||||
```
|
||||
main.js → Electron main process: IPC handlers, API calls (axios), profile CRUD,
|
||||
camera proxy process spawning, password encryption (CryptoJS + machine-derived key)
|
||||
camera proxy process spawning, password encryption (CryptoJS + machine-derived key),
|
||||
local HTTP cookie server for Chrome extension bridge
|
||||
preload.js → contextBridge exposing window.electronAPI with typed IPC invoke wrappers
|
||||
renderer.js → All UI logic: DOM manipulation, state management, event handlers
|
||||
index.html → Static HTML shell, no inline scripts (CSP enforced)
|
||||
styles.css → Dark theme using CSS custom properties
|
||||
```
|
||||
|
||||
A companion Chrome extension lives in `chrome-extension/`:
|
||||
|
||||
```
|
||||
chrome-extension/
|
||||
manifest.json → Manifest V3, cookies + activeTab permissions
|
||||
popup.html → Extension popup UI
|
||||
popup.css → Dark theme matching the Electron app
|
||||
popup.js → Tab detection, cookie retrieval, POST to localhost
|
||||
icon*.png → Placeholder icons
|
||||
```
|
||||
|
||||
### IPC Communication Pattern
|
||||
|
||||
All cross-process communication follows one pattern:
|
||||
Most cross-process communication follows the request/response pattern:
|
||||
1. `main.js` registers handler: `ipcMain.handle('channel-name', async (event, params) => { ... })`
|
||||
2. `preload.js` exposes it: `channelName: (params) => ipcRenderer.invoke('channel-name', params)`
|
||||
3. `renderer.js` calls it: `const result = await window.electronAPI.channelName(params)`
|
||||
|
||||
All handlers return `{ success: boolean, message?: string, ...data }`.
|
||||
|
||||
There is one **push-pattern** channel for the Chrome extension cookie bridge:
|
||||
- `main.js` sends: `mainWindow.webContents.send('extension-cookie-received', data)`
|
||||
- `preload.js` bridges: `ipcRenderer.on('extension-cookie-received', callback)`
|
||||
- `renderer.js` listens via `window.electronAPI.onExtensionCookie(callback)`
|
||||
|
||||
### IPC Channels
|
||||
|
||||
| Channel | Purpose |
|
||||
@@ -52,6 +75,7 @@ All handlers return `{ success: boolean, message?: string, ...data }`.
|
||||
| `camera-proxy-stop` | Kills all proxy processes via taskkill/powershell |
|
||||
| `camera-proxy-check` | Checks if proxy executable exists |
|
||||
| `camera-proxy-version` | Runs proxy with -v flag |
|
||||
| `extension-cookie-received` | Push channel: cookie data from Chrome extension → renderer |
|
||||
|
||||
### State Management (renderer.js)
|
||||
|
||||
@@ -68,11 +92,25 @@ Active proxy processes are tracked in two Maps: `activeProxyConnections` and `ac
|
||||
- Legacy profiles auto-migrate from old static key on first load
|
||||
- Clipboard is cleared 30 seconds after password copy
|
||||
- Passwords never written to DOM; kept only in JS variables (`selectedProfile`)
|
||||
- Local HTTP cookie server (port 18247) bound to `127.0.0.1` only
|
||||
- Cookie server validates: shared token header, CORS restricted to `chrome-extension://` origins, deployment URL must be `*.avasecurity.com` or `*.avigilon.com` over HTTPS, type/length limits on all inputs, 64KB body size limit
|
||||
|
||||
### Profile Storage
|
||||
|
||||
Profiles stored at `~/.alta-api-profiles.json`. Passwords encrypted with CryptoJS AES using a machine-derived key. The `profiles-load` handler strips passwords before sending to renderer; `profiles-get` decrypts for a specific profile when needed.
|
||||
|
||||
### Chrome Extension Cookie Bridge
|
||||
|
||||
Users already logged into Alta in Chrome can send their `va` session cookie to the running Electron app. The flow:
|
||||
|
||||
1. Chrome extension popup detects Alta tab (`*.avasecurity.com` / `*.avigilon.com`)
|
||||
2. User clicks "Send Cookie to APT"
|
||||
3. Extension POSTs `{deploymentUrl, cookieValue}` to `http://127.0.0.1:18247/cookie` with `X-APT-Token` header
|
||||
4. `main.js` HTTP server validates and forwards via IPC push to renderer
|
||||
5. `renderer.js` `handleExtensionCookie()` sets session state, populates cookie key, expands cookie proxy section, fetches devices
|
||||
|
||||
The extension is loaded unpacked via `chrome://extensions/` → Developer mode → Load unpacked → select `chrome-extension/`.
|
||||
|
||||
## Key Conventions
|
||||
|
||||
- No inline event handlers in HTML — all use `addEventListener` in renderer.js
|
||||
@@ -86,4 +124,4 @@ Profiles stored at `~/.alta-api-profiles.json`. Passwords encrypted with CryptoJ
|
||||
- `aware-cam-proxy-win.exe` — username/password auth proxy (required)
|
||||
- `aware-cam-proxy.exe` — cookie-based auth proxy (optional)
|
||||
|
||||
These are not bundled via npm. They must be in the app root directory.
|
||||
These are not bundled via npm. They must be in the app root directory. They are gitignored along with `*.pdf`, `node_modules/`, and `dist/`.
|
||||
|
||||
Reference in New Issue
Block a user