Repository navigation
feat(channels): agents tui logs in to Cloudflare Access by itself - #2462
Conversation
This PR makes `agents tui` handle a Web Channel URL behind Cloudflare Access, so connecting to a deployed agent needs no token plumbing. ## Why - Agents deployed to a team account are usually behind Access. Today the TUI connects only with a service token in the environment, or a `cf-access-token` header pasted by hand from `cloudflared access token`. - Developers already have `cloudflared` for this. The TUI can ask it for the token, the way Wrangler and the Vite plugin handle Access for remote bindings. ## Public API Surface No new exports. `agents tui <url>` now: - detects Access from the redirect a plain request to the URL's origin gets - runs `cloudflared access token -app=<origin>`, and `cloudflared access login <origin>` first when there is no token yet - sends the token as `cf-access-token` on the WebSocket upgrade Service-token variables, `--header cf-access-token=…` and cookies still take precedence, and URLs not behind Access are untouched. ## Code Changes - `web/tui/access.ts` holds the detection and the `cloudflared` calls, with injectable fetch and process runners. If `cloudflared` is missing, it explains how to pass the header instead. - `web/tui/main.ts` adds the headers before starting the TUI. `--help` describes the Access behaviour. - `tui-access.test.ts` covers the cases with stubbed redirects and commands. - Patch changeset for `agents`.
🦋 Changeset detectedLatest commit: 0039286 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| args = { ...args, headers: { ...args.headers, ...access } }; | ||
| } catch (error) { |
There was a problem hiding this comment.
🔴 Expired Access tokens strand live sessions
When an Access token expires, sendHeadersOnUpgrade keeps sending it on reconnects. WebChannelClient retries with the same headers, leaving the TUI disconnected until restart.
Learn more
The TUI resolves an Access token once, then sendHeadersOnUpgrade captures that token in the WebSocket wrapper. The client's reconnect loop reuses the wrapper without refreshing its headers. When Access expires the token, all future upgrade attempts use an expired token until the process exits.
Example: A TUI starts at 09:00 with a token expiring at 10:00. If the socket drops at 10:05, every automatic retry uses the 09:00 token instead of obtaining a new one.
Recommended fix: Refresh cloudflared credentials before retries after an Access rejection or before reconnecting when the JWT has expired. Make the WebSocket upgrade wrapper read updated headers on each connection and avoid restarting interactive login for unrelated connection failures.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
✅ agents import sizes: no significant changes ( |
…ccess's cookie Access can protect a path rather than a whole host, so the TUI now probes and logs in to the address it opens. A cookie header skips the lookup only when it carries CF_Authorization.
| const app = url.toString(); | ||
| if (!(await behindAccess(app, deps))) return {}; |
There was a problem hiding this comment.
This PR makes
agents tuihandle a Web Channel URL behind Cloudflare Access, so connecting to a deployed agent needs no token plumbing.Why
cf-access-tokenheader pasted by hand fromcloudflared access token.cloudflaredfor this. The TUI can ask it for the token, the way Wrangler and the Vite plugin handle Access for remote bindings.Public API Surface
No new exports.
agents tui <url>now:cloudflared access token -app=<origin>, andcloudflared access login <origin>first when there is no token yetcf-access-tokenon the WebSocket upgradeService-token variables,
--header cf-access-token=…and cookies still take precedence, and URLs not behind Access are untouched.Code Changes
web/tui/access.tsholds the detection and thecloudflaredcalls, with injectable fetch and process runners. Ifcloudflaredis missing, it explains how to pass the header instead.web/tui/main.tsadds the headers before starting the TUI.--helpdescribes the Access behaviour.tui-access.test.tscovers the cases with stubbed redirects and commands.agents.