fix(auth): stop gated HuggingFace models bouncing users to /login - #88
Merged
Conversation
Selecting a gated model on the New Benchmark or Estimate page could redirect the user to /login. The model-config endpoints (/recommend, /estimate, /memory-breakdown) fetch config from HuggingFace, which returns 401 for gated models (or a missing/expired platform token, or rate-limiting). The handlers relayed that 401 verbatim, and the frontend's fetchJSON treats any 401 as an expired session. The symptom only showed with auth disabled: with auth enabled the silent /auth/refresh succeeds and the retried 401 falls through to the normal error path, but with auth disabled /auth/refresh returns 503, so the refresh always fails and the redirect fires every time. Fix, both layers: - Backend: new writeHFError helper remaps an HF 401/403 to 422 so it never collides with the app's own auth 401, preserving the "model is gated — provide an HF token" message. Wired into handleRecommend, handleMemoryBreakdown, and handleEstimate. - Frontend: the auth middleware now sets WWW-Authenticate on genuine auth 401s; fetchJSON only runs its refresh + redirect flow when that marker is present, protecting every current and future endpoint from the same misclassification. Adds regression tests: gated 401/403 -> 422 across all three endpoints with auth disabled, generic HF error -> 502, and WWW-Authenticate presence on auth 401s. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Problem
A user reported being redirected to
/loginwhen selecting a model from the MODEL (HUGGINGFACE ID) dropdown on the New Benchmark page — while switching between several models. It only reproduced when auth is disabled.Root cause
Selecting a model fires
GET /recommend,/memory-breakdown, and (on the Estimate page)/estimate. Each fetches the model config from HuggingFace. For a gated model — or a missing/expired platform HF token, or HF rate-limiting — HuggingFace returns 401, and the handlers relayed that status verbatim. The frontend'sfetchJSONtreats any 401 as a session expiry: it tries a silent/auth/refreshand, on failure, redirects to/login.Why auth-disabled-only: with auth enabled the silent refresh succeeds and the retried 401 falls through to the normal error path (no redirect). With auth disabled,
/auth/refreshreturns 503, so the refresh always fails and the redirect fires every time. The middleware had already injected a synthetic admin, so it was never a real auth failure.Fix (two layers)
writeHFErrorhelper remaps a HuggingFace 401/403 to 422 Unprocessable Entity (preserving the actionable "model is gated — provide an HF token" message); non-HFErrorfailures become 502. Wired intohandleRecommend,handleMemoryBreakdown, andhandleEstimate.WWW-Authenticate: Beareron genuine auth 401s;fetchJSONruns its refresh + redirect flow only when that marker is present. This protects every current and future endpoint from the same misclassification.Audit
Full sweep of gated-model entry points. The bug surface is exactly the three
fetchJSONendpoints that fetch HF config, reached fromRun.tsx(recommend + memory-breakdown) andEstimate.tsx(estimate). Everywhere else is safe:ModelComboboxhits HuggingFace directly via rawfetch(not wrapped byfetchJSON) and already shows an inline gated warning;ModelCacheand the create-run POSTs don't fetch HF config.Tests
go test ./...✅ ·go vet ./...✅ — new regression tests: gated 401/403 → 422 across all three endpoints with auth disabled, generic HF error → 502,WWW-Authenticatepresent on auth 401.npx tsc --noEmit✅ ·npm run build✅ ·npm test✅ (21 tests).Deploy note
Touches both backend and frontend, so both
accelbench-apiandaccelbench-webneed to be rebuilt/pushed and rolled.🤖 Generated with Claude Code