fix(login): drop Accept header — /auth/exchange POST blocked by CORS preflight (P0 follow-up)#151
Merged
Conversation
…(P0 follow-up) Follow-up to #150. chrome MCP live verification showed POST /auth/exchange returning net::ERR_FAILED — root cause: the `Accept: application/json` header on the fetch forced a CORS preflight. OPTIONS preflight 403'd because `Accept` isn't in the api's `corsAllowHeaders` allowlist (Content-Type, Authorization, X-Request-ID, X-E2E-Test-Token, X-E2E-Source-IP). Confirmed with direct curl: OPTIONS /auth/exchange + Access-Control-Request-Headers: accept → 403 Forbidden. Fix: drop the Accept header. A POST with only safelisted headers + credentials:include is a "simple cross-origin request" — no preflight needed. The api returns JSON regardless of the request Accept value. Regression test: assert init.headers is undefined so a future maintainer who reintroduces Accept / Content-Type gets caught by the existing test pass before merge. `npm run gate` clean locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
size-limit report 📦
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
P0 follow-up to #150. That PR added the AUTH-004 cookie-exchange flow but the fetch call included
Accept: application/json, which forced a CORS preflight that the api'sPreflightAllowlistrejects. Live login was still broken after #150 shipped.Root cause
Live verification via chrome devtools MCP:
Confirmed with direct curl:
api's allowlist (
api/internal/router/router.go:242):Acceptisn't in it → preflight 403 → browser blocks the POST with the generic "Failed to fetch" error.Fix
Drop the
Acceptheader. With only safelisted headers +credentials: 'include', the POST becomes a "simple cross-origin request" — no preflight required. The api returns JSON regardless of the requestAcceptvalue.Test coverage block (rule 17)
Symptom: POST
/auth/exchangereturnsnet::ERR_FAILEDin browser; CORS preflight 403 confirmed via curlEnumeration:
rg -nF 'corsAllowHeaders' internal/router/router.go(1 hit, allowlist excludes Accept)Sites found: 1 (LoginCallbackPage.tsx
exchangeCookieForToken)Sites touched: 1
Coverage test: new regression guard asserts
init.headersisundefined— catches any future reintroduction of Accept/Content-Type that would re-break the preflightLive verified: will re-verify with chrome MCP after merge + GH Pages deploy
Why didn't #150 catch this
Unit tests mock
fetchso they never exercise the real browser's CORS preflight logic. This is a class of bug that only surfaces in live cross-origin tests. CLAUDE.md rule 13 is explicit: "Live-URL gate. Every user-facing change ends with one of: (a) curl of the prod URL grep'd for the new SHA/content, (b) a real triggered email/webhook/job artifact, (c) explicit 'awaiting user verification of X'. Log greps DO NOT satisfy this gate." I treatednpm run gategreen as sufficient — that's the mistake.🤖 Generated with Claude Code