Skip to content

Commit adfc84c

Browse files
Make auth handoff default to real auth links
1 parent 97cb574 commit adfc84c

11 files changed

Lines changed: 107 additions & 103 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ sequenceDiagram
8181
C-->>B: page state
8282
B-->>A: snapshot or result
8383
alt login or challenge required
84-
A->>B: auth_request or lease_control_request
84+
A->>B: auth_request
8585
B-->>H: one-time portal URL
8686
H->>C: human completes login
8787
end

ax_browser_broker/api.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
)
4242
from .docs import docs
4343
from .feedback import FeedbackError, list_issues, report_issue, update_issue
44-
from .identities import IdentityError, invalidate_identity_replicas, redacted_status
44+
from .identities import IdentityError, invalidate_identity_replicas, redacted_status, require_identity
4545
from .lease_control import (
4646
LeaseControlError,
4747
complete_control_session,
@@ -152,7 +152,7 @@ class AuthRequest(BaseModel):
152152
reason: str = "login_required"
153153
identity_id: str | None = None
154154
profile: str | None = None
155-
mode: str = "lease_control"
155+
mode: str = "vnc"
156156
ttl_seconds: int = Field(default=900, ge=60, le=14400)
157157
control_ttl_seconds: int = Field(default=900, ge=60, le=3600)
158158
wait_until: str = "domcontentloaded"
@@ -233,6 +233,8 @@ def _active_identity_lease_id(identity_id: str | None) -> str | None:
233233

234234

235235
def _active_identity_control_redirect(auth_request_data: dict[str, Any], error: AuthError) -> RedirectResponse | None:
236+
if str(auth_request_data.get("mode") or "vnc") == "vnc":
237+
return None
236238
identity_id = str(auth_request_data.get("identity_id") or "")
237239
message = str(error)
238240
if not identity_id or "actively leased" not in message:
@@ -268,11 +270,13 @@ def _url_host(url: str | None) -> str:
268270

269271

270272
async def _legacy_vnc_auth_request(request: AuthRequest) -> dict[str, Any]:
273+
if request.identity_id:
274+
require_identity(request.identity_id)
271275
result = create_auth_request(request.owner, request.url, request.reason, request.identity_id, mode=request.mode)
272276
_safe_record_event(
273277
source=request.owner,
274278
event_type="auth",
275-
message="Legacy VNC auth request created",
279+
message="Auth handoff request created",
276280
url=request.url,
277281
tags=["auth", "vnc", request.reason],
278282
data={"token": result.get("token"), "status": result.get("status"), "identity_id": request.identity_id},
@@ -365,11 +369,11 @@ async def _active_identity_control_response(request: AuthRequest) -> dict[str, A
365369

366370

367371
async def _open_auth_lease_control(request: AuthRequest) -> dict[str, Any]:
372+
if request.mode == "vnc":
373+
return await _legacy_vnc_auth_request(request)
368374
active_response = await _active_identity_control_response(request)
369375
if active_response:
370376
return active_response
371-
if request.mode == "vnc":
372-
return await _legacy_vnc_auth_request(request)
373377
lease_obj = await create_lease(
374378
LeaseRequest(owner=request.owner, ttl_seconds=request.ttl_seconds, identity_id=request.identity_id)
375379
)
@@ -404,10 +408,10 @@ async def _open_auth_lease_control(request: AuthRequest) -> dict[str, Any]:
404408
_safe_record_event(
405409
source=request.owner,
406410
event_type="session",
407-
message="Auth request opened lease control",
411+
message="Explicit lease-control auth fallback opened",
408412
lease_id=lease_id,
409413
url=navigation.get("url") or request.url,
410-
tags=["auth", "lease-control", "default"],
414+
tags=["auth", "lease-control", "explicit"],
411415
data={
412416
"slot": lease_obj.get("name"),
413417
"identity_id": request.identity_id,

ax_browser_broker/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def build_parser() -> argparse.ArgumentParser:
232232
open_cmd.add_argument("--no-verify", action="store_true", help="Skip the post-navigation snapshot receipt")
233233
open_cmd.set_defaults(func=cmd_open)
234234

235-
auth = sub.add_parser("auth", help="Create an auth handoff or active lease-control response")
235+
auth = sub.add_parser("auth", help="Create a real /auth/<token> login handoff")
236236
auth.add_argument("url")
237237
auth.add_argument("--identity", default=None)
238238
auth.add_argument("--owner", default="openbrowser-cli")
@@ -242,8 +242,8 @@ def build_parser() -> argparse.ArgumentParser:
242242
auth.add_argument(
243243
"--mode",
244244
choices=["lease_control", "vnc"],
245-
default="lease_control",
246-
help="lease_control is the default; vnc is the legacy full-login-view fallback",
245+
default="vnc",
246+
help="vnc is the default real login portal; lease_control is only for explicit current-tab control fallback",
247247
)
248248
auth.set_defaults(func=cmd_auth)
249249

ax_browser_broker/docs.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
],
5959
"rules": [
6060
"Use broker identities such as work-main or qa-generic when account state is needed.",
61-
"Use auth_request for login or password handoff; auth_request returns lease_control by default.",
62-
"Use lease_control_request when an already-leased browser hits a human challenge or login prompt that must be handled in the current tab.",
61+
"Use auth_request for login or password handoff; auth_request returns a real /auth/<token> portal by default.",
62+
"Use lease_control_request only when an already-leased browser needs human current-tab control without credential entry.",
6363
"Use OpenBrowser wrappers instead of aiming custom scripts directly at raw pool CDP ports.",
6464
"For chat/editor submission, prefer broker keyboard tools over DOM fill because modern editors maintain internal state.",
6565
"For Slack header/tab controls, dismiss open ReactModal/popovers with Escape before selector clicks.",
@@ -118,7 +118,7 @@
118118
"notes": [
119119
"The CLI talks to the local broker API and reads the local server-side API key file when needed.",
120120
"Use open --control for simple 'open this for me' requests; it returns a verified control URL in one command.",
121-
"openbrowser auth returns an interactive lease-control URL by default. Use --mode vnc only for the legacy full-login-view fallback.",
121+
"openbrowser auth returns a real /auth/<token> login portal by default. Use open --control or lease-control for current-tab control links.",
122122
"Use it for status, docs, auth handoffs, active lease-control links, and quick smoke checks.",
123123
"Use Broker MCP directly for normal click/type/screenshot workflows when tools are available.",
124124
],
@@ -127,22 +127,21 @@
127127
"title": "Human Auth Handoff",
128128
"steps": [
129129
"When an agent hits a login wall, call auth_request with owner, url, reason, and identity_id.",
130-
"auth_request returns lease_control by default: a broker lease is opened or reused, navigated to the requested URL when safe, verified with a compact snapshot, and exposed through the normal control portal.",
131-
"If the requested identity is already leased, auth_request returns lease_control for that active browser instead of opening a competing Chrome profile.",
132-
"If the active leased browser is on a different host than the requested URL, auth_request returns takeover_required=true and does not navigate the active browser.",
133-
"If no identity_id is supplied, auth_request opens a neutral broker browser and returns a warning instead of using a personal authenticated profile.",
134-
"Send the returned portal_url to the human operator only after checking status, current_url/navigation, snapshot, and takeover_required.",
135-
"Use mode=vnc only when the legacy full-login-view fallback is explicitly needed.",
136-
"During legacy VNC identity auth, the broker pauses the matching pool slot with a maintenance marker so headless Chrome cannot re-lock the profile.",
130+
"auth_request returns a real /auth/<token> login portal by default. Send this link when the user must sign in, enter a password, use a passkey, solve 2FA, or complete a provider login flow.",
131+
"If the requested identity is already leased, do not convert login auth into lease-control. Release your own stale lease first, or wait if another agent owns the lease.",
132+
"Use lease_control_request only when the user explicitly needs to control an already-open current tab, not for credential entry.",
133+
"If no identity_id is supplied, auth_request creates a neutral auth portal and does not use a personal authenticated profile.",
134+
"Send the returned portal_url only when it starts with /auth/ and not /auth/lease-control/ for login tasks.",
135+
"Use mode=lease_control only for the explicit current-tab fallback. Do not use it for login.",
136+
"During identity auth, the broker pauses the matching pool slot with a maintenance marker so headless Chrome cannot re-lock the profile.",
137137
"If the identity has proxy_ref, the legacy temporary auth Chrome also uses that proxy through ax-proxy-forwarder.",
138-
"If a legacy VNC identity auth handoff is refused before VNC starts, the temporary VNC password file is removed.",
139-
"When legacy VNC completion runs, the broker stops VNC/websockify/Chrome/Xvfb helper processes and removes the temporary password file.",
140-
"After a lease-control handoff, continue from the same lease_id/current tab. Do not create a second lease or navigate away from a meaningful page.",
138+
"If an identity auth handoff is refused before VNC starts, the temporary VNC password file is removed.",
139+
"When auth completion runs, the broker stops VNC/websockify/Chrome/Xvfb helper processes and removes the temporary password file.",
140+
"After auth completion, lease the same identity, snapshot first, and continue from the authenticated state. After lease-control, continue from the same lease_id/current tab.",
141141
"After browser work, confirm state with snapshot or screenshot and run broker_audit.",
142142
],
143143
"examples": [
144144
{"tool": "auth_request", "args": {"owner": "agent-name", "url": "https://example.com/login", "reason": "profile_login", "identity_id": "work-main"}},
145-
{"tool": "auth_request", "args": {"owner": "agent-name", "url": "https://example.com/login", "reason": "legacy_vnc_login", "identity_id": "work-main", "mode": "vnc"}},
146145
{"tool": "lease_control_request", "args": {"owner": "agent-name", "lease_id": "<lease_id>", "ttl_seconds": 900}},
147146
],
148147
},

ax_browser_broker/mcp_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,13 @@ def auth_request(
257257
url: str,
258258
reason: str = "login_required",
259259
identity_id: str | None = None,
260-
mode: Literal["lease_control", "vnc"] = "lease_control",
260+
mode: Literal["vnc", "lease_control"] = "vnc",
261261
ttl_seconds: int = 900,
262262
control_ttl_seconds: int = 900,
263263
wait_until: str = "domcontentloaded",
264264
verify: bool = True,
265265
) -> dict[str, Any]:
266-
"""Create a human auth handoff. Defaults to lease-control; pass mode='vnc' only for the legacy login-view fallback."""
266+
"""Create a real /auth/<token> login handoff. Use mode='lease_control' only for explicit current-tab control fallback."""
267267
return _request(
268268
"POST",
269269
"/auth/request",

ax_browser_broker/remote_mcp_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,13 @@ def auth_request(
228228
url: str,
229229
reason: str = "login_required",
230230
identity_id: str | None = None,
231-
mode: Literal["lease_control", "vnc"] = "lease_control",
231+
mode: Literal["vnc", "lease_control"] = "vnc",
232232
ttl_seconds: int = 900,
233233
control_ttl_seconds: int = 900,
234234
wait_until: str = "domcontentloaded",
235235
verify: bool = True,
236236
) -> dict[str, Any]:
237-
"""Create a human auth handoff. Defaults to lease-control; pass mode='vnc' only for the legacy login-view fallback."""
237+
"""Create a real /auth/<token> login handoff. Use mode='lease_control' only for explicit current-tab control fallback."""
238238
return _request(
239239
"POST",
240240
"/auth/request",

docs/browser-routing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ flowchart TD
99
NeedAuth -->|Yes| Identity["Lease named identity"]
1010
Identity --> Login{"Login wall?"}
1111
Login -->|No| Act["Navigate, click, type, screenshot"]
12-
Login -->|Yes| Handoff["auth_request or lease_control_request"]
12+
Login -->|Yes| Handoff["auth_request -> /auth/<token>"]
1313
Generic --> Act
1414
Handoff --> Act
1515
Act --> Release["Release lease"]
@@ -31,7 +31,7 @@ flowchart TD
3131
1. Lease before browser work.
3232
2. Use identities only when account state or proxy routing is required.
3333
3. Use `auth_request` for login, passkeys, 2FA, or password entry.
34-
4. Use `lease_control_request` when a human must control the currently leased tab.
34+
4. Use `lease_control_request` only when a human must control the currently leased tab without entering credentials.
3535
5. Release every lease.
3636
6. Run `broker_audit` after browser-agent work.
3737
7. Do not connect custom scripts directly to raw pool CDP ports during normal agent work.

0 commit comments

Comments
 (0)