Skip to content

Require a token on every call from the server to a Bot - #52

Open
zopeVaibhav wants to merge 1 commit into
CopilotKit:mainfrom
zopeVaibhav:fix/agent-bot-auth-token
Open

Require a token on every call from the server to a Bot#52
zopeVaibhav wants to merge 1 commit into
CopilotKit:mainfrom
zopeVaibhav:fix/agent-bot-auth-token

Conversation

@zopeVaibhav

Copy link
Copy Markdown
Contributor

The problem

agent-bot and agent-langgraph serve POST /ag-ui without any authentication. Any process that can reach the Bot's port issues an AG-UI run against the deployment's model credential; docker-compose.yml:162 binds ${BOT_PORT:-4200}:4200 on 0.0.0.0, so on the shipped configuration that is any process on the host's network and any container on the compose network. MANAGED_AGENT_TOKEN is not read anywhere in either Bot, and server/src/agents/runtime-agents.ts attaches no authentication header to its own calls, so the boundary is absent on both sides rather than misconfigured. agent-computer and supervisor both require a shared secret at boot and validate it on every request; the two Bots did not.

This is the opposite direction to #34, which added per-agent callback tokens for the Bot→server path. That change does not cover requests from the server into a Bot's /ag-ui, which is what this PR closes.

Closes #50.

The approach

A single header, x-openbot-agent-token, on every call from the server to a managed Bot. A new shared/agent-authorisation.ts holds a constant-time matchesToken and a hasManagedAgentToken request helper, kept in shared/ so the two Bots and the server all read the same rule rather than three subtly different ones. Both Bots refuse to start when MANAGED_AGENT_TOKEN is unset, no silent-open dev fallback because the process holds a model credential and an unauthenticated port on it is worth failing loudly for, and reject /ag-ui with 401 when the header is missing or wrong. GET /health stays open so an orchestrator can check readiness without holding the token.

The server side matches. server/src/config.ts requires MANAGED_AGENT_TOKEN at boot alongside the other secrets. server/src/agents/runtime-agents.ts attaches the header only on the agent whose endpoint equals config.managedAgentAgUiUrl, so customer-owned AG-UI endpoints never see it and a token intended for the built-in Bot is not leaked to a third party's server on the first customer registration. docker-compose.yml passes MANAGED_AGENT_TOKEN through to both Bots; .env.example, README.md, and docs/configuration.md document the new required variable.

What is not covered

  • Only the wire between the server and the managed Bots. Customer-registered AG-UI endpoints authenticate through their own write-only header, unchanged. This PR does not touch that path.
  • Not a rotation mechanism. Changing the token is a redeploy of the server plus a compose recreate of the two Bots. Fine at this scale, not for a mid-flight rotation.
  • agent-computer and supervisor were already token-guarded and are unchanged.
  • The header name is not part of AG-UI. It is an OpenBot-specific header; anyone forking a Bot needs to add the check.

Merge notes

  • New required env var: MANAGED_AGENT_TOKEN. Existing deployments that upgrade without setting it get a loud refuse-to-start on both the server and each Bot rather than a silent regression.
  • Config type gains a required managedAgentToken: string; loadConfig test fixtures are updated.
  • createRuntimeAgentLoader gains an optional trailing managedAgent parameter; existing callers that pass undefined keep their old behaviour but issue no header, so a self-hosted deployment that runs a custom Bot in place of the managed one needs to opt in.

Verification

All gates from a clean tree at c81d9b1.

  • bun run format:check: no fixes

  • bun run lint: 25 pre-existing noTemplateCurlyInString warnings, none new

  • bun run typecheck: app, server, worker all exit 0

  • bun run test: 686 pass, 5 skip, 0 fail across 79 files, 1701 assertions

  • bun run build: exit 0

  • Live against a rebuilt openbot-agent-bot container (docker compose up -d --build --force-recreate agent-bot):

    request result
    POST /ag-ui, no headers 401 Unauthorized.
    POST /ag-ui, x-openbot-agent-token: wrong 401
    POST /ag-ui, x-openbot-agent-token: $MANAGED_AGENT_TOKEN 200, RUN_STARTED
    GET /health 200 (unchanged)

New tests: shared/agent-authorisation.test.ts (2). Existing tests updated: server/tests/config.test.ts (required-token assertion), server/tests/runtime-agents.integration.test.ts (managed endpoint receives header, customer endpoint does not).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

agent-bot and agent-langgraph accept unauthenticated /ag-ui runs

1 participant