Skip to content

fix(coderd/externalauth): detect concurrent refresh race to prevent cache poisoning (#24228)#25508

Merged
f0ssel merged 1 commit into
release/2.32from
backport/24228-to-2.32
May 19, 2026
Merged

fix(coderd/externalauth): detect concurrent refresh race to prevent cache poisoning (#24228)#25508
f0ssel merged 1 commit into
release/2.32from
backport/24228-to-2.32

Conversation

@github-actions
Copy link
Copy Markdown

Backport of #24228

Original PR: #24228 — fix(coderd/externalauth): detect concurrent refresh race to prevent cache poisoning
Merge commit: da6e708
Requested by: @f0ssel

…ache poisoning (#24228)

<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->

Fixes #17069

Builds on #24332 and #24334 which addressed token persistence and rate
limit handling.

## Problem

When multiple concurrent requests race to refresh an expiring external
auth token, providers with single-use refresh tokens (e.g., GitHub Apps)
reject all but the first refresh attempt with `bad_refresh_token`. The
losing request caches this transient error in the
`oauth_refresh_failure_reason` database column and clears the refresh
token, blocking all subsequent refresh attempts until the user manually
re-authenticates.

This is common for users with multiple terminals, IDE connections, or
workspaces open, all of which poll the external auth endpoint and
trigger concurrent refreshes when the token nears expiry. Database
analysis showed 5 of 7 affected users failed within 5-10 seconds of
token expiry, matching the Go oauth2 library's `expiryDelta` window.

## Fix

Before caching a `bad_refresh_token` failure, re-read the external auth
link from the database. If the refresh token has changed (indicating a
concurrent caller already refreshed successfully), return the winner's
updated link instead of writing a failure. An empty-string guard ensures
a token cleared by another loser isn't mistaken for a winner's
successful refresh.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Garrett Delfosse <[email protected]>
(cherry picked from commit da6e708)
@github-actions github-actions Bot requested a review from f0ssel May 19, 2026 20:38
@f0ssel f0ssel merged commit 26e1515 into release/2.32 May 19, 2026
@f0ssel f0ssel deleted the backport/24228-to-2.32 branch May 19, 2026 20:43
@github-actions github-actions Bot locked and limited conversation to collaborators May 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants