-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Bug: Concurrent requests can invalidate refresh tokens due to missing deduplication
Severity: medium
Location: server/replit_integrations/auth/replitAuth.ts — isAuthenticated (lines 221-243)
Background / Context
The isAuthenticated middleware checks whether the access token has expired and, if so, calls client.refreshTokenGrant with the user's refresh token. There is no deduplication: if multiple concurrent requests arrive for the same user after token expiry, each independently calls refreshTokenGrant with the same refresh token.
Many OIDC providers rotate refresh tokens on each use, invalidating the old token once exchanged. This means only the first concurrent request succeeds; subsequent ones fail because the token they hold has been consumed.
How to Reproduce
- User has an active session with an expired access token.
- Two or more API requests arrive simultaneously (e.g., the frontend dashboard fires parallel fetches on page load).
- Both requests enter
isAuthenticated, both read the same expireduser.expires_at, both callrefreshTokenGrantwith the same refresh token value. - The first request succeeds and the OIDC provider rotates the refresh token.
- The second request's
refreshTokenGrantcall fails with an invalid grant error.
Actual Result
The second (and any additional) concurrent request receives a 401 Unauthorized response. Users may see partial page load failures or be unexpectedly redirected to the login page.
Expected Result
Concurrent refresh attempts for the same session should be deduplicated. A standard approach is a per-session in-flight promise cache: the first request initiates the refresh and stores the pending promise; concurrent requests await the same promise rather than issuing duplicate refresh calls.
Found by
Automated bug reporter during magicwand pipeline review of PR #266.