Skip to content

fix(auth): /auth/me + admin routes accept cq_session cookie (closes login 401) - #252

Merged
dwinter3 merged 1 commit into
mainfrom
fix/auth-me-reads-cookie
May 14, 2026
Merged

fix(auth): /auth/me + admin routes accept cq_session cookie (closes login 401)#252
dwinter3 merged 1 commit into
mainfrom
fix/auth-me-reads-cookie

Conversation

@dwinter3

Copy link
Copy Markdown

Post-FO-1d the React admin shell carries only the cq_session HttpOnly cookie (no Authorization header). _resolve_caller in auth.py only inspected the Authorization header — so /auth/me and every route fronted by get_current_user 401'd even with a valid cookie set by /auth/login. Root cause of the smoke-test login loop: POST /auth/login returns 200 + Set-Cookie cq_session, but GET /auth/me 401s because the server never read the cookie, React shows login screen on repeat. Fix: one fallback in _resolve_caller — when no Authorization: Bearer header is present, decode cq_session via web_session.read_session_from_cookie before 401'ing. Header still wins when both present, so API-key callers are unaffected. Tests: added test_me_with_cookie_only; patched test_confirm_and_flag_require_api_key to clear TestClient cookie jar. 137 related tests pass.

… cookie

Post-FO-1d the React admin shell strips the Authorization header and
relies exclusively on the HttpOnly cq_session cookie. But _resolve_caller
in auth.py only ever inspected the Authorization header — so even after
/auth/login successfully minted the cookie, /auth/me (and every other
route fronted by get_current_user) returned 401 because no header meant
"no credential" to the server.

The fix is a one-line fallback in _resolve_caller: if no Bearer header
is present, decode the cq_session cookie via web_session.read_session_from_cookie
before 401'ing. Header still wins when both are present, so explicit
api-key intent is honored and existing CLI/script callers are unaffected.

Adds test_me_with_cookie_only to lock in the browser path and patches
test_confirm_and_flag_require_api_key to clear the TestClient cookie
jar between the seed login and the no-creds assertion (the seed leaves
a valid cookie behind that — correctly — would now authenticate).
@dwinter3
dwinter3 merged commit d858a25 into main May 14, 2026
2 checks passed
@dwinter3
dwinter3 deleted the fix/auth-me-reads-cookie branch May 14, 2026 10:27
dwinter3 added a commit that referenced this pull request May 15, 2026
…267)

The new CodeBuild CI gate (#168) made main's red server suite visible.
All 7 failures were stale tests, not product bugs — features shipped
correctly, their tests just weren't updated:

- HEAD_REVISION pins (3 files: test_default_enterprise_backfill,
  test_migration_0011_activity_log, test_migration_0015_*) hardcoded
  "0023_persona_assignment_audit". Migration 0024_user_tour_state
  (founder tour, #254) correctly bumped HEAD_REVISION; the test pins
  didn't follow. Bumped to 0024 + de-staled the comments.
- test_queries TestUserHelpers — raw INSERT_USER param dicts omitted
  `role` (the column the role-propagation fix #252/#253 added to the
  INSERT), and the SELECT row indices still assumed the pre-role column
  order. Added role to the dicts; fixed row[3]/row[4] indexing.
- test_review test_get_requires_auth — _propose() logs in, persisting
  the cq_session cookie in the TestClient jar; since cookie auth
  landed, that cookie authenticates the "no header" request. Clear the
  jar so it exercises the genuine unauthenticated path.

Full server suite: 858 passed, 5 skipped, 0 failed.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
dwinter3 added a commit that referenced this pull request May 16, 2026
…01 (#272)

agent#166 reported POST /api/v1/auth/login 504-hanging when the users
table is empty (filed against the phase18-crosstalk image, 2026-05-09).

Not reproducible on current main: the handler's `user is None`
short-circuit returns a 401 before verify_password is reached, and
get_user is a plain indexed SELECT that returns None instantly on an
empty table. Verified two ways — `test_login_unknown_user` already
exercises the unseeded-table path (suite green), and a live probe
against the engineering L2 returns 401 in ~0.35s. The auth handler was
also reworked post-filing (#251/#252/#253).

Adds an explicit regression test for the exact agent#166 scenario
(genuinely-empty users table, not just unknown-user) with a generous
elapsed-time guard, so a future hang is caught as a fast failure rather
than a CI timeout.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant