Repository navigation
fix: refresh the wrangler OAuth token and retry once on 401 - #9
Merged
Merged
Conversation
The token provider refreshed only when the stored expiration_time was near, so a token the API rejected while its stored expiry still looked valid caused a hard 401 (code 10000). The client now asks the provider for a replacement on a 401 and retries the request once. The provider re-reads wrangler's config before refreshing, so a token wrangler already refreshed (and a rotated refresh token) is adopted instead of spending a stale refresh token. Concurrent refreshes share one token request. Closes #8 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
Review round 1
Verified correct: the shared refresh promise always clears and can't run twice at once; concurrent 401s share one refresh; the retry sends the same request; API-token users don't change (no hook, so no retry); no new type escapes. Findings
|
…h failure Without persisting (or when the write-back fails), a second 401 re-adopted the already rejected token from the file and refreshed with a spent refresh token. The provider now keeps the newest credentials in memory, adopts the file only when it changed since the last read or write, and never reuses a rejected token. When the refresh itself fails, the client error now keeps the request URL and the original 401 body, and the refresh error includes the token endpoint's response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
Response to review round 1
|
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.
Closes #8
Problem
With
wrangler logincredentials,oblaka --remotefailed hard with401 Authentication error(code 10000). The token provider only refreshed when the storedexpiration_timewas within the expiry buffer, andCloudflareClient.fetchthrew on any non-OK response. A token the API rejected while its stored expiry still looked valid could not be recovered;wrangler whoami(which rewrites the stored token) was the workaround.The exact cause of the original failure is not proven: wrangler itself refreshes only after the stored expiry has passed and has no 401 retry. This PR adds the refresh-and-retry safeguard the issue asks for, so a rejected OAuth token is recovered either way.
Change
createWranglerTokenProvidernow returns{ getToken, refreshToken }.getToken()keeps the expiry-based refresh (same flow and endpoint as wrangler).refreshToken(rejected)returns a replacement for a token the API rejected. It first re-reads wrangler's config: if the file changed since oblaka last read or wrote it (wrangler refreshed, possibly rotating the refresh token), it adopts that instead of spending a stale refresh token. Otherwise it refreshes and persists, as before.--no-persist-tokenor a failed write-back doesn't lead to reusing a rejected token or a spent refresh token.CloudflareClienttakes an optionalrefreshTokenhook. On a 401 it asks for a replacement and retries the request once. If the retry is rejected too, the error carries awrangler loginhint. If the refresh itself fails, the error keeps the request URL and the original 401 body, and the refresh error includes the token endpoint's response. WithCLOUDFLARE_API_TOKENthere is no hook, so nothing changes.Tests
tests/auth.test.ts: refresh of a rejected token whose stored expiry is still valid (persisted), adopting a token wrangler wrote meanwhile, concurrent refresh dedupe (expiry path and concurrent 401s), rotated refresh token reused without persisting, refresh failure propagating the hint and endpoint body.tests/client.test.ts: 401, then refresh and a successful retry; POST retried with the same body; a second 401 fails with the hint; a failed refresh keeps the request context; no retry without a hook.Ran locally:
bun test(129 pass),bun run typecheck,bun run lint,bun run format:check.Status
🤖 Generated with Claude Code