Description
The OAuth callback server started on port 19876 during authenticate() is never stopped after authentication completes (success or failure). The server remains bound to the port for the lifetime of the process.
This causes cross-instance CSRF errors when multiple opencode TUI instances are running:
- Instance A starts, triggers OAuth → callback server starts on port 19876 → auth succeeds → server stays running
- Instance B starts, triggers OAuth →
ensureRunning() detects port in use → skips server start
- Instance B registers its OAuth state in its own process-local
pendingAuths Map
- Browser callback arrives at port 19876 → handled by Instance A → Instance A's
pendingAuths is empty → "Invalid or expired state parameter - potential CSRF attack"
Steps to reproduce
- Start opencode TUI (Instance A) with a remote MCP server requiring OAuth
- Complete OAuth authentication successfully
- Start another opencode TUI (Instance B) in a different terminal
- Instance B attempts OAuth for the same MCP server
- Browser opens, user approves, but callback fails with CSRF error
Expected behavior
The callback server should stop after authentication completes (when no other OAuth flows are pending), releasing port 19876 for subsequent auth flows.
Actual behavior
The callback server remains running indefinitely. McpOAuthCallback.stop() is never called after authenticate() completes. The only callers of stop() are:
- Internal reconfiguration in
ensureRunning() (when port/path changes)
- Test cleanup (
afterEach)
Proposed fix
Add a stopIfIdle() function that stops the server only when pendingAuths is empty, and call it after authenticate() completes. This is safe for concurrent auth flows — the server only stops when all pending auths are resolved.
OpenCode version
1.14.19
Related issues
Description
The OAuth callback server started on port 19876 during
authenticate()is never stopped after authentication completes (success or failure). The server remains bound to the port for the lifetime of the process.This causes cross-instance CSRF errors when multiple opencode TUI instances are running:
ensureRunning()detects port in use → skips server startpendingAuthsMappendingAuthsis empty → "Invalid or expired state parameter - potential CSRF attack"Steps to reproduce
Expected behavior
The callback server should stop after authentication completes (when no other OAuth flows are pending), releasing port 19876 for subsequent auth flows.
Actual behavior
The callback server remains running indefinitely.
McpOAuthCallback.stop()is never called afterauthenticate()completes. The only callers ofstop()are:ensureRunning()(when port/path changes)afterEach)Proposed fix
Add a
stopIfIdle()function that stops the server only whenpendingAuthsis empty, and call it afterauthenticate()completes. This is safe for concurrent auth flows — the server only stops when all pending auths are resolved.OpenCode version
1.14.19
Related issues