Skip to content

Conversation

@tjementum
Copy link
Member

Summary & Motivation

Fix the token refresh race condition introduced in #821. When multiple API requests are made concurrently and all attempt to refresh an expired access token, only one succeeds while the others fail with DbUpdateConcurrencyException, causing the user to be logged out. This commonly occurs when returning to a browser tab after tokens have expired (e.g., TanStack Query's invalidateQueries() triggers multiple parallel requests).

  • Implement atomic token refresh using an isolated database connection that commits immediately, independent of EF Core's Unit of Work transaction. This ensures only one concurrent request wins the refresh race, while others fall back to the grace period mechanism using PreviousRefreshTokenJti
  • Update SQLite test connection strings to use shared cache mode (Cache=Shared), enabling isolated connections to access the same in-memory database. This allows the atomic refresh pattern using Activator.CreateInstance(existingConnection.GetType()) to work in tests
  • Simplify RefreshTokenGenerator API by consolidating Generate and Update methods into a single Generate method with explicit version and expiry parameters
  • Reorder UserInfoFactory parameters to follow async conventions with cancellationToken last
  • Remove SessionRefreshed and AuthenticationTokensRefreshed telemetry events as they add noise without providing meaningful business value

Downstream projects

Update the SQLite connection string in your-self-contained-system/Tests/EndpointBaseTest.cs to use shared cache mode, which allows isolated database connections to access the same in-memory database:

-        // Create connection and add DbContext to the service collection
-        Connection = new SqliteConnection("DataSource=:memory:");
+        // Create connection using shared cache mode so isolated connections can access the same in-memory database
+        Connection = new SqliteConnection($"Data Source=TestDb_{Guid.NewGuid():N};Mode=Memory;Cache=Shared");

Checklist

  • I have added tests, or done manual regression tests
  • I have updated the documentation, if necessary

@tjementum tjementum self-assigned this Jan 11, 2026
@tjementum tjementum added the Bug Something isn't working label Jan 11, 2026
@linear
Copy link

linear bot commented Jan 11, 2026

@tjementum tjementum moved this to 🏗 In Progress in Kanban board Jan 11, 2026
@sonarqubecloud
Copy link

@tjementum tjementum merged commit de84c2a into main Jan 11, 2026
27 checks passed
@tjementum tjementum deleted the pp-756-token-refresh-fails-when-multiple-concurrent-requests-occur branch January 11, 2026 20:20
@github-project-automation github-project-automation bot moved this from 🏗 In Progress to ✅ Done in Kanban board Jan 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant