hai login: browser sign-in for every account - #229
H-maximedelpit wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 89b1346. Configure here.
| return _mint_key(client, portal, org_id, label)["key"] | ||
| body = token.json() | ||
| client.headers["Authorization"] = f"Bearer {body['access_token']}" | ||
| return _mint_for_signed_in_user(client, portal, label, session_id=body.get("session_id")) |
There was a problem hiding this comment.
Session revoke never receives session id
High Severity
The exchange POST never sends X-SDK-Auth, so portal session_id stays on the cookie and body.get("session_id") is empty. The later session DELETE is skipped, and the web session created by sign-in remains valid even though the API key is supposed to be the only leftover credential.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 89b1346. Configure here.
There was a problem hiding this comment.
Quoting Fable:
Re "Session revoke never receives session id": checked against portal-h domains/auth/controller.py, desktop_exchange returns DesktopExchangeOutput(access_token, refresh_token, session_id) as the JSON body; it is not the cookie-mode login response, so X-SDK-Auth does not apply and body.get("session_id") is populated. The revoke runs. Covered by test_minting_names_the_identity_and_revokes_the_web_session. No change.


Purpose
hai loginonly works for Google accounts: it sends the browser to the portal withprovider=google, so the CLI, the quickstart, the onboarding emails and the Agents API docs all reject email + password users. With hcompai/portal-h#865 and hcompai/platform-frontend#779, the CLI can let the platform login page handle any account. This PR is the recommended path; #228 is the exclusive terminal-password alternative.What it does
provider=google. The portal sends the browser to the platform login page, where Google and email + password both finish back on the CLI's loopback listener. Loopback, PKCE and/desktop/exchangeare unchanged.hai login --keystill exists for machines without a browser.What it does not do
HAI_API_KEYonly); the stored-key fallback branches are parked unmerged by decision.Alternatives rejected
non_oauth_usererror and falling back to a key-paste prompt: works today without portal changes, but still leaves non-Google users one step short of a one-click login. Dropped in favour of the portal change.Dependencies and merge order
app.py), merge, release. The new CLI gets a 400 from an old portal, so do not release early; the current CLI keeps working throughout.hai login.🤖 Generated with Claude Code
Note
High Risk
Changes the CLI authentication flow (authorize URL, session lifecycle, and post-login identity display) in security-sensitive login and key-minting code; depends on coordinated portal/frontend deploys.
Overview
hai loginbrowser sign-in no longer forces Google: the authorize URL dropsprovider=googleso the portal can send users to the platform login page (Google or email/password) while loopback, PKCE, and/desktop/exchangestay the same.After a successful mint,
login_and_mintreturns aSignedInrecord (key, email, optional organization name). The CLI printsSigned in as <email> in organization <name>so a key landed in the wrong account is obvious, then saves the key. It also DELETEs the temporary web session once the API key exists (errors on revoke are ignored).Docs and
KEY_FALLBACKare updated for multi-method browser login andhai login --keywithout a browser. New unit tests cover authorize URL shape, mint/revoke ordering, and the identity line.Reviewed by Cursor Bugbot for commit 89b1346. Bugbot is set up for automated code reviews on this repo. Configure here.