Frontend: send access token, refresh once on 401 #59

Merged
ryan merged 1 commits from fix/access-token-auth into main 2026-10-12 17:49:18 -04:00
Owner

Release 2 of 2 for the auth fix (phase 0a in docs/desktop-client.md). Requires #57 to be live on both colors (it is): the pre-#57 backend answers access tokens with 422.

Changes

  • userService.fetchWithAuth replaces both fetchWithRefreshToken and the old fetchWithAuth: sends the access token, refreshes up front when none is stored, and on a 401 refreshes once and retries. Concurrent refreshes share one /refresh call.
  • The refresh token is now only sent to POST /api/user/refresh; validateToken still uses it.
  • oidcService.initiateLogin no longer sends the ignored ?redirect=.

Deploy / rollback

  • make redeploy.
  • From here on, never roll back past #57.
  • Later (separate PR): tighten jwt_access_required to access-only and map WrongTokenError to 401 so stale tabs refresh instead of getting a 422.

Test plan

  • yarn build
  • Network tab: API calls use the access token; refresh token only goes to /api/user/refresh
  • Delete access_token from localStorage and reload: still logged in
  • Image upload and a streamed answer both work

🤖 Generated with Claude Code

Release 2 of 2 for the auth fix (phase 0a in docs/desktop-client.md). Requires #57 to be live on both colors (it is): the pre-#57 backend answers access tokens with 422. ## Changes - `userService.fetchWithAuth` replaces both `fetchWithRefreshToken` and the old `fetchWithAuth`: sends the access token, refreshes up front when none is stored, and on a 401 refreshes once and retries. Concurrent refreshes share one `/refresh` call. - The refresh token is now only sent to `POST /api/user/refresh`; `validateToken` still uses it. - `oidcService.initiateLogin` no longer sends the ignored `?redirect=`. ## Deploy / rollback - `make redeploy`. - From here on, never roll back past #57. - Later (separate PR): tighten `jwt_access_required` to access-only and map WrongTokenError to 401 so stale tabs refresh instead of getting a 422. ## Test plan - [x] `yarn build` - [ ] Network tab: API calls use the access token; refresh token only goes to `/api/user/refresh` - [ ] Delete `access_token` from localStorage and reload: still logged in - [ ] Image upload and a streamed answer both work 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ryan added 1 commit 2026-10-12 17:48:49 -04:00
Collapse fetchWithRefreshToken/fetchWithAuth into a single fetchWithAuth
that sends the access token, refreshes up front when none is stored, and
on a 401 refreshes once (deduplicated across concurrent calls) and retries.
The refresh token is now only sent to /api/user/refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ryan merged commit 1a73e26f23 into main 2026-10-12 17:49:18 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ryan/simbarag#59