Skip to content

Bug: Concurrent requests can invalidate refresh tokens due to missing deduplication #269

@bd73-com

Description

@bd73-com

Bug: Concurrent requests can invalidate refresh tokens due to missing deduplication

Severity: medium
Location: server/replit_integrations/auth/replitAuth.tsisAuthenticated (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

  1. User has an active session with an expired access token.
  2. Two or more API requests arrive simultaneously (e.g., the frontend dashboard fires parallel fetches on page load).
  3. Both requests enter isAuthenticated, both read the same expired user.expires_at, both call refreshTokenGrant with the same refresh token value.
  4. The first request succeeds and the OIDC provider rotates the refresh token.
  5. The second request's refreshTokenGrant call 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmediumMedium severity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions