Skip to content

fix(auth): prevent concurrent signup race conditions and lost updates - #552

Open
Namraa310806 wants to merge 3 commits into
FireFistisDead:masterfrom
Namraa310806:fix/concurrent-signup-race-condition
Open

fix(auth): prevent concurrent signup race conditions and lost updates#552
Namraa310806 wants to merge 3 commits into
FireFistisDead:masterfrom
Namraa310806:fix/concurrent-signup-race-condition

Conversation

@Namraa310806

@Namraa310806 Namraa310806 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a race condition in the user registration flow that could cause lost updates and inconsistent user data during concurrent signup requests.

Previously, the authentication system used a read-modify-write pattern on users.json without synchronization. Multiple simultaneous registration requests could read the same file state, perform independent modifications, and overwrite each other's changes when writing back to disk.

This update introduces file locking, atomic writes, and concurrency-safe registration handling to ensure reliable user persistence under concurrent workloads.


Changes Made

Concurrency-Safe User Registration

  • Added file locking using proper-lockfile.
  • Ensured only one signup operation can modify users.json at a time.
  • Prevented concurrent write conflicts during registration.

Duplicate User Validation Under Lock

Moved duplicate-email validation inside the protected critical section.

This ensures:

  • The latest file state is always checked.
  • Concurrent signup requests cannot bypass duplicate checks.
  • User uniqueness is maintained under load.

Atomic File Writes

Implemented atomic write operations using:

users.json.tmp → rename → users.json

Benefits:

  • Prevents partial writes.
  • Reduces risk of file corruption.
  • Improves reliability during unexpected crashes or interruptions.

Lock Cleanup & Error Handling

Added safe lock release logic for:

  • Successful registrations
  • Validation failures
  • Unexpected exceptions

This prevents stale locks and improves recovery behavior.

Regression Test Coverage

Added concurrent registration tests covering:

  • Multiple simultaneous signup requests
  • Lost update prevention
  • Duplicate email handling
  • File consistency verification

Reliability Impact

This change improves:

  • User data consistency
  • Concurrent request handling
  • Registration reliability
  • File integrity during writes

The application can now safely process concurrent signup requests without risking lost registrations or corrupted user data.


Security Impact

This change reduces the risk of:

  • Race-condition exploits
  • Duplicate account creation through concurrent requests
  • Data integrity violations
  • Authentication inconsistencies caused by lost updates

Files Modified

src/controllers/authController.js
Authentication test suite

Verification Checklist

  • File locking implemented
  • Duplicate checks performed under lock
  • Atomic file writes added
  • Lock cleanup implemented
  • Concurrent registration tests added
  • Lost-update vulnerability resolved
  • Existing authentication functionality preserved
  • No breaking API changes introduced

Related Issue

Fixes #503

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved signup reliability by preventing data races during concurrent registrations.
    • Added safer handling for duplicate email and missing/invalid signup fields, with consistent error responses.
  • Tests

    • Expanded integration coverage for POST /api/auth/signup, including success, duplicate rejection, password strength checks, missing fields, and concurrent signups.
  • Chores

    • Updated dependencies to improve lock-based file operation reliability.

@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

@Namraa310806 is attempting to deploy a commit to the firefistisdead's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d19bc2ef-a510-49e1-9c54-ea17a1e51520

📥 Commits

Reviewing files that changed from the base of the PR and between e1380ac and 48845be.

📒 Files selected for processing (2)
  • src/controllers/authController.js
  • src/data/users.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/controllers/authController.js
  • src/data/users.json

📝 Walkthrough

Walkthrough

The PR adds proper-lockfile and reworks signup to lock users.json during read-modify-write operations. It also adds signup integration tests for success, duplicates, concurrency, weak passwords, and missing fields, plus updated fixture users.

Changes

Concurrent-safe signup with file locking

Layer / File(s) Summary
Dependency and locked helpers
package.json, src/controllers/authController.js
Adds proper-lockfile and introduces locked read/write helpers for users.json with temp-file persistence and lock release handling.
Locked signup flow
src/controllers/authController.js
Reworks signup to normalize input, validate password strength, hash the password, check for duplicate emails while holding the lock, persist the new user, and release the lock in normal and error paths.
Signup tests and fixture users
server.test.js, src/data/users.json
Adds POST /api/auth/signup integration tests for success, duplicate rejection, concurrent requests, weak passwords, and missing fields, and updates users.json with matching test accounts.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant signup
  participant lockfile
  participant users.json

  Client->>signup: POST /api/auth/signup
  signup->>signup: validate email and password
  signup->>lockfile: lock users.json
  lockfile-->>signup: release function
  signup->>users.json: read current users
  alt email already exists
    signup->>lockfile: release()
    signup-->>Client: 400 User already exists
  else new user
    signup->>users.json: write updated users via temp file
    signup->>lockfile: release()
    signup-->>Client: 201 + token
  end
  alt error
    signup->>lockfile: release() in catch
    signup-->>Client: 500 Server error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #469 — Similar signup/user-file access changes; this PR adds file locking around concurrent registrations, which matches the issue’s concurrency objective.

Poem

🐇 I hopped through signup, neat and tight,
A little lock kept writes polite.
No lost bunnies in the stack,
Every token found its track.
Hooray for files that stay in line,
And users saved just one at a time!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing concurrent signup race conditions and lost updates.
Description check ✅ Passed The description covers the bug, the locking/atomic-write fix, tests, impact, and related issue, with only minor template fields missing.
Linked Issues check ✅ Passed The changes address #503 by adding signup synchronization, atomic writes, duplicate checks under lock, and concurrency tests.
Out of Scope Changes check ✅ Passed The added dependency, tests, auth logic, and users.json data all support the concurrent-signup fix and appear in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added backend Express or API gateway work bug Something isn't working duplicate This issue or pull request already exists enhancement New feature or request feature A new feature or improvement fix A targeted fix or cleanup frontend Frontend-related work level:critical rag-service FastAPI / model service work type:security type:testing labels Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/controllers/authController.js (1)

2-2: ⚡ Quick win

Remove unused symbols flagged by CI (fsPromises, saveUsers).

Line 2 and Lines 22-24 are now dead after the locked helper migration, and they keep lint warnings active.

Proposed cleanup
-const fsPromises = require("fs/promises");
@@
-const saveUsers = (users) => {
-  fs.writeFileSync(usersFile, JSON.stringify(users, null, 2));
-};

Also applies to: 22-24

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/controllers/authController.js` at line 2, Remove the unused fsPromises
import statement from line 2 and delete the saveUsers function definition from
lines 22-24. These symbols became dead code after the locked helper migration
and are causing lint warnings. Ensure no other code references these symbols
before deletion.

Sources: Linters/SAST tools, Pipeline failures

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server.test.js`:
- Around line 988-1014: The test "POST /api/auth/signup - concurrent
registrations prevent lost updates" currently only verifies HTTP response status
codes and token presence, but does not verify that all three users were actually
persisted in the database. A lost-update bug could still pass this test by
returning 201 for all concurrent requests while failing to store some users.
After the Promise.all(promises) completes and you verify the successCount, add
post-signup verification by attempting to login each of the three users with
their respective email and password credentials. Verify that each login attempt
succeeds to confirm all three accounts were actually persisted, ensuring the
test truly catches lost-update bugs rather than just checking surface-level
response codes.
- Around line 946-1050: The signup tests (POST /api/auth/signup - single user
registration succeeds, POST /api/auth/signup - duplicate email is rejected, POST
/api/auth/signup - concurrent registrations prevent lost updates, POST
/api/auth/signup - validates password strength, POST /api/auth/signup - rejects
missing email or password) are writing directly to the real src/data/users.json
file and not cleaning up afterward, causing state to persist across test runs.
To fix this, implement test isolation by either mocking the user data store with
an in-memory implementation specific to each test, using a temporary test
fixture that gets restored after each test, or implementing setup/teardown hooks
to clear or reset the users.json file before and after each test runs. Ensure
that each test operates on isolated state that does not affect subsequent test
runs or the committed repository state.

In `@src/controllers/authController.js`:
- Around line 43-45: The empty catch block at line 45 that follows the
fs.unlinkSync(tempFile) call is violating the ESLint no-empty rule and is hiding
potential cleanup failures. Replace the empty catch block with proper error
handling by either logging the error that occurred during the file deletion
attempt (using a logger at an appropriate level like warn or debug since this is
cleanup code) or adding an explanatory comment if the error is intentionally
ignored. This will satisfy the linter and provide visibility into cleanup
failures for debugging purposes.

---

Nitpick comments:
In `@src/controllers/authController.js`:
- Line 2: Remove the unused fsPromises import statement from line 2 and delete
the saveUsers function definition from lines 22-24. These symbols became dead
code after the locked helper migration and are causing lint warnings. Ensure no
other code references these symbols before deletion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cadb328-991e-440d-a208-fe9e282f4a8e

📥 Commits

Reviewing files that changed from the base of the PR and between 5590b87 and e1380ac.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json
  • server.test.js
  • src/controllers/authController.js
  • src/data/users.json

Comment thread server.test.js
Comment thread server.test.js
Comment thread src/controllers/authController.js Outdated
@Namraa310806

Copy link
Copy Markdown
Contributor Author

@FireFistisDead ready to merge without merge conflicts

@github-actions github-actions Bot added the invalid This doesn't seem right label Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Express or API gateway work bug Something isn't working duplicate This issue or pull request already exists enhancement New feature or request feature A new feature or improvement fix A targeted fix or cleanup frontend Frontend-related work invalid This doesn't seem right level:critical rag-service FastAPI / model service work type:security type:testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Concurrent User Registrations Can Cause Lost Updates Due to Unsynchronized users.json Writes

1 participant