feat(server): add authenticated remote access and desktop bootstrap

Adds cookie-based login with a bootstrap token flow for desktop apps, secures OpenCode instance traffic with per-instance Basic auth, and updates UI/plugin clients to use credentials.
This commit is contained in:
Shantur Rathore
2026-01-14 18:18:14 +00:00
parent 927e4e1281
commit 40634138bc
27 changed files with 1721 additions and 160 deletions

View File

@@ -103,7 +103,7 @@ async function request<T>(path: string, init?: RequestInit): Promise<T> {
logHttp(`${method} ${path}`)
try {
const response = await fetch(url, { ...init, headers })
const response = await fetch(url, { ...init, headers, credentials: init?.credentials ?? "include" })
if (!response.ok) {
const message = await response.text()
logHttp(`${method} ${path} -> ${response.status}`, { durationMs: Date.now() - startedAt, error: message })
@@ -135,6 +135,15 @@ export const serverApi = {
fetchServerMeta(): Promise<ServerMeta> {
return request<ServerMeta>("/api/meta")
},
fetchAuthStatus(): Promise<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }> {
return request<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }>("/api/auth/status")
},
setServerPassword(password: string): Promise<{ ok: boolean; username: string; passwordUserProvided: boolean }> {
return request<{ ok: boolean; username: string; passwordUserProvided: boolean }>("/api/auth/password", {
method: "POST",
body: JSON.stringify({ password }),
})
},
deleteWorkspace(id: string): Promise<void> {
return request(`/api/workspaces/${encodeURIComponent(id)}`, { method: "DELETE" })
},
@@ -270,7 +279,7 @@ export const serverApi = {
},
connectEvents(onEvent: (event: WorkspaceEventPayload) => void, onError?: () => void) {
sseLogger.info(`Connecting to ${EVENTS_URL}`)
const source = new EventSource(EVENTS_URL)
const source = new EventSource(EVENTS_URL, { withCredentials: true } as any)
source.onmessage = (event) => {
try {
const payload = JSON.parse(event.data) as WorkspaceEventPayload