Session log — Zoom Apps, OBF cross-account support

← All session logs

Session log — Zoom Apps, OBF cross-account support

16 May 2026 · Hasmukh with Claude · Camera Monitor v0.7.0 → v0.9.0

Summary

Picked up from the v0.7.0 distribution-ready baseline and built OBF (On Behalf Of) authentication so Camera Monitor can join meetings hosted by accounts outside Mobilearn. Previously, the bot used ZAK with the built-in cameramonitor@mobilearn.africa identity, limiting it to Mobilearn-hosted meetings. With OBF, an operator authorises Camera Monitor against their own Zoom account once via a browser OAuth flow, and the bot then joins meetings on their behalf, working for any host.

Built v0.8.0 with the full OBF stack: a local HTTP callback server on port 8765 inside the Electron main process, browser-based OAuth via shell.openExternal, encrypted token storage via Electron safeStorage, an "Authorise Zoom" UI button with green / grey status banner, and a fallback chain that prefers OBF when authorised and falls back to ZAK otherwise. First test failed with a 400 from /v2/users/me which needs the user:read scope we did not add; v0.8.1 made that fetch optional. OBF then worked end to end on a non-auth-required meeting.

For the auth-required external meeting case, OBF failed with errorCode 3051. Initially attributed to a Web SDK Embedded limitation but at end of session realised the authorising user was not actually in the meeting during the test, even though OBF requires their presence. Re-test next session before declaring this case unsupported.

Wrapped by bumping to v0.9.0, updating OPERATOR-GUIDE.html and .md with the new OBF workflow plus the provisional auth-required limitation, rebuilding the DMG, and updating project memory.

Decisions

  • Build OBF on the existing General App "Camera Status Companion" rather than register a new one. The General App already had Meeting SDK enabled; the change was just adding the OAuth redirect URL and user:read:token scope.
  • OAuth redirect URL is http://localhost:8765/oauth-callback. Allow list http://localhost:8765. Both Strict Mode and Subdomain Check unticked.
  • Keep ZAK as a fallback rather than ripping it out. ZAK covers the Mobilearn bot identity scenario; OBF covers operator-on-behalf. obfToken and zak are mutually exclusive in client.join() so the renderer picks at most one per join.
  • Per-operator OAuth tokens are stored encrypted via Electron safeStorage with macOS Keychain backing.
  • Make /v2/users/me fetch optional. Failing it should not break authorisation. Display falls back to "Zoom user" placeholder. Cosmetic only.
  • v0.9.0 marks the official "Shape A + OBF" milestone, ready for redistribution to the studio team.

Changes made

  • main.js: added safeStorage, shell, http, crypto, fs imports. Added the OBF stack: startOAuthFlow spins up a local HTTP server on port 8765 with state token verification and a 5 minute timeout, exchangeCodeForTokens does the authorization_code grant, refreshAccessToken handles refresh, fetchZoomUserInfo is optional and graceful, saveTokens / loadTokens / clearTokens use safeStorage with plaintext fallback, ensureFreshAccessToken refreshes with a 60s safety margin, getOBFToken calls /v2/users/me/token?type=onbehalf&meeting_id=X. Added four IPC handlers: zoom:authorize-user, zoom:auth-status, zoom:deauthorize, zoom:get-obf.
  • renderer/index.html: added div#oauth-status row at the top of the join form with status text, Authorise Zoom button, Sign out button.
  • renderer/styles.css: added #oauth-status styles with .authorised class state for the green look.
  • renderer/renderer.js: refreshAuthStatusUI pulls auth-status on load. Authorise button triggers the OAuth flow. Sign out clears tokens. Join logic tries OBF first when authorised, falls back to ZAK otherwise; obfToken and zak spread mutually exclusively into client.join.
  • package.json: bumped through 0.8.0, 0.8.1, 0.9.0.
  • OPERATOR-GUIDE.md and .html: added Step 1a "Authorise for external meetings" section, reworked Rule 2 to explain the two modes, added Rule 2a for the provisional external + auth-required limitation, updated troubleshooting, bumped footer to v0.9.0.
  • Published yesterday's two session logs to documentation.mobilearn.africa at the start of this session.
  • Updated project memory with v0.9.0 architecture and the open re-test item.

Follow-ups

  • Top priority next session: re-test OBF + auth-required with the authorising user actually in the meeting first. If it works, the documented Rule 2a limitation can be removed; bump to v0.9.1 and update OPERATOR-GUIDE. If it still fails, implement the proposed ZAK fallback on errorCode 3051.
  • Add user:read scope to the Camera Status Companion Marketplace app so the green banner shows the actual operator email rather than "Zoom user".
  • Redistribute v0.9.0 DMG plus updated OPERATOR-GUIDE.html to the studio team.
  • Long-term: publish the Marketplace app so accounts outside Mobilearn can authorise without being added to the dev whitelist.
  • Shape B (server-side bot) still parked, Recall.ai vs self-hosted decision still open.