Gate OAuth token refresh on credential store writability - #1377
Merged
Conversation
A vault write failure while persisting a refreshed OAuth token lost the rotated refresh token: the grant had already consumed the single-use stored token at the authorization server, so once the vault recovered the next refresh replayed the revoked token, got invalid_grant, and the connection demanded a re-auth over what was only a storage blip. Before consuming the refresh token, rewrite the stored value in place as a writability probe. A store outage now fails the resolve before the grant, leaving the stored token valid so the connection recovers with the store.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | b02cb53 | Commit Preview URL Branch Preview URL |
Aug 28 2026, 06:28 AM |
Contributor
Cloudflare previewTorn down — the PR is closed. |
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | b02cb53 | Aug 28 2026, 06:29 AM |
Main now persists the rotated refresh token before the access token, so the ordering half of this failure is fixed. The writability half is not: when the store refuses writes outright, the grant has already spent the stored token and there is nowhere to put its successor. Keep the pre-flight rewrite that proves the store is writable before the grant, move its scenario into the existing credential-write-durability suite rather than standing up a second file, and drop the prose that still claimed the persist ordering was wrong. Skip the persist's own refresh-token write when the authorization server hands back an unrotated token, so the probe removes a vault write on the common path instead of adding one.
The writability gate proved the store by rewriting the refresh token with the value it had just read. That is a read-then-write with no compare-and-set, so two instances refreshing one connection lose the newer token: one reads the stored token, the other spends it and stores the rotated replacement, and the first then writes the spent one back over it. The in-flight refresh gate is per instance and cannot see the peer. The gate now writes a fixed value to an item of its own, derived from the refresh item's id so it lands in the same store partition and proves the same thing. It holds no credential, so nothing is at risk when two refreshers race on it.
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.
A secret-store write failure while persisting a refreshed OAuth token could permanently invalidate the connection: the refresh grant had already consumed the single-use refresh token at the authorization server, so the rotated replacement was lost and the next refresh was rejected with invalid_grant, forcing a reconnect over what was only a transient storage error.
The refresh path now rewrites the stored refresh token in place before consuming it, so a store outage fails the request before the grant and the connection recovers once the store does. Includes an e2e scenario that stages the outage against the WorkOS emulator's vault and pins both the surfaced error and the recovery contract.