[eric] auth: dev-only /api/dev/token so the split-port frontend can authenticate (404s when packaged)

This commit is contained in:
eric
2026-06-01 11:55:17 -07:00
parent 1a4a23f131
commit bcb88ebefb
4 changed files with 49 additions and 0 deletions
+3
View File
@@ -186,6 +186,9 @@ _AUTH_EXEMPT_EXACT = {
# public api.openswarm.com/api/oauth/google/refresh doesn't already
# do for any internet caller, so no new attack surface.
"/api/tools/google-oauth-token",
# Dev-only token handoff for the split-port frontend (no Electron preload
# to read the token from). The route itself 404s in packaged builds.
"/api/dev/token",
}
_AUTH_EXEMPT_PREFIX = (
+11
View File
@@ -386,6 +386,17 @@ async def websocket_dashboard(websocket: WebSocket):
ws_manager.disconnect_global(websocket)
@app.get("/api/dev/token")
async def dev_token():
"""Hand the per-install token to the dev frontend, which has no Electron
preload to read it from. Disabled in packaged builds (the preload exists
there); localhost binding is the only thing gating it in dev."""
if os.environ.get("OPENSWARM_PACKAGED") == "1":
return JSONResponse({"error": "not available"}, status_code=404)
from backend.auth import get_auth_token
return JSONResponse({"token": get_auth_token()})
@app.post("/api/browser/command")
async def browser_command(request: Request):
"""HTTP endpoint called by the browser MCP server subprocess.
+23
View File
@@ -268,3 +268,26 @@ def test_signout_succeeds_even_when_cloud_unreachable(client, reset_settings):
s2 = load_settings()
assert s2.user_id is None
assert s2.openswarm_bearer_token is None
# ---------------------------------------------------------------------------
# The dev-token handoff must be dev-only so it can't widen prod surface (#49).
# ---------------------------------------------------------------------------
def test_dev_token_is_dev_only():
"""/api/dev/token hands the install token to the split-port dev frontend
without auth, but 404s in packaged builds where the preload supplies it."""
import os
import backend.auth as auth_mod
noauth = TestClient(app) # deliberately no bearer header
os.environ.pop("OPENSWARM_PACKAGED", None)
r = noauth.get("/api/dev/token")
assert r.status_code == 200
assert r.json()["token"] == auth_mod._TOKEN
os.environ["OPENSWARM_PACKAGED"] = "1"
try:
assert noauth.get("/api/dev/token").status_code == 404
finally:
os.environ.pop("OPENSWARM_PACKAGED", None)
+12
View File
@@ -23,6 +23,18 @@ export async function refreshAuthToken(): Promise<string> {
} catch {
_authTokenCache = '';
}
return _authTokenCache;
}
// Dev (split-port, no Electron preload): the backend hands us the token over
// localhost. The route 404s in packaged builds, so this only fires under run.sh.
try {
const r = await fetch(`http://${host}:${port}/api/dev/token`);
if (r.ok) {
const data = await r.json();
_authTokenCache = typeof data?.token === 'string' ? data.token : '';
}
} catch {
_authTokenCache = '';
}
return _authTokenCache;
}