Skip to content

fix(clipboard): add 30-second TTL to clear pasted content from state#716

Open
Vox-d-glitch wants to merge 2 commits into
rinafcode:mainfrom
Vox-d-glitch:security/auth-client-lockout
Open

fix(clipboard): add 30-second TTL to clear pasted content from state#716
Vox-d-glitch wants to merge 2 commits into
rinafcode:mainfrom
Vox-d-glitch:security/auth-client-lockout

Conversation

@Vox-d-glitch

Copy link
Copy Markdown
Contributor

Summary

  • Added authFailureCount, authLockedUntil, and refreshFailureCount fields to useAppStore; authLockedUntil is persisted to secure storage so a force-close does not reset an active lockout
  • incrementAuthFailure locks the login form for 30 seconds and resets the count after 5 consecutive 401s on /auth/login; resetAuthFailures clears both count and timestamp on successful login
  • incrementRefreshFailure tracks consecutive /auth/refresh 401s and triggers a full logout() at 3, preventing a broken auth loop
  • Axios response interceptor calls resetAuthFailures() on a successful login response; error interceptor calls incrementAuthFailure() on login 401s and incrementRefreshFailure() on refresh 401s
  • MobileLogin shows an amber countdown banner and disables the submit button for the full 30-second lockout window using a 1-second interval tied to authLockedUntil
  • Unit tests cover: incremental count, lock threshold at 5, no lock before 5, reset clears count and lockout, force-logout at 3 refresh failures, and logout zeroing all counters

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Chore / Refactor (no functional changes)

Testing Done

  • Unit Tests
  • Integration Tests
  • Manual Verification (e.g., iOS/Android UI checks)

Security Considerations

  • Does this store user data securely (e.g., avoiding plain AsyncStorage for sensitive data)? — authLockedUntil is persisted via secureStorageJSONStorage (expo-secure-store), not plain AsyncStorage
  • Is token handling secure (no token exposure in logs or UI)? — No credentials or tokens appear in any log calls added; only status codes and endpoint names are logged
  • Are all user inputs validated? — N/A to this change
  • Is deep link handling safe from malicious payloads? — N/A to this change

Performance Considerations

  • Are React hooks (useCallback, useMemo) used appropriately to prevent unnecessary renders? — Lockout state is read via a fine-grained Zustand selector (state => state.authLockedUntil) to avoid unnecessary re-renders
  • Is FlatList optimized (e.g., using getItemLayout, keyExtractor)? — N/A to this change
  • Are asynchronous patterns handled correctly (e.g., useEffect cleanup to avoid memory leaks)? — Countdown interval is cleared in the useEffect cleanup on unmount or when authLockedUntil changes
  • Have bundle size impacts been considered? — No new dependencies

Checklist

  • I have read the CONTRIBUTING guide.
  • My code follows the style guidelines of this project.
  • I have updated the documentation accordingly. — Store actions are self-documenting via Zustand devtools action names; no external docs affected
  • Are there architectural changes? If so, is there an Architectural Decision Record (ADR)? — No architectural changes; lockout logic is scoped to the existing store and interceptor

Closes #577

The mobile client had no friction against credential stuffing — failed
login attempts were retried immediately via the existing exponential
backoff logic designed for network errors, not auth failures.

- Store: add authFailureCount, authLockedUntil, refreshFailureCount
  fields and incrementAuthFailure / resetAuthFailures /
  incrementRefreshFailure actions to useAppStore; authLockedUntil is
  persisted to secure storage so a force-close does not bypass the lock
- Interceptor: count 401s on /auth/login (increments on each failed
  attempt, lock triggers at 5); reset counter on successful login
  response; force-logout after 3 consecutive /auth/refresh 401s
- MobileLogin: show amber countdown banner and disable submit button
  for the 30-second lockout window
- Tests: unit tests covering threshold, early-exit, reset-on-success,
  force-logout at 3 refresh failures, and logout clearing all counters

Closes rinafcode#581
@drips-wave

drips-wave Bot commented Jun 27, 2026

Copy link
Copy Markdown

@Vox-d-glitch Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Vox-d-glitch Vox-d-glitch changed the title Security/auth client lockout fix(clipboard): add 30-second TTL to clear pasted content from state Jun 27, 2026
@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Kindly resolve conflict

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] No rate limiting on authentication endpoints — brute-force risk

2 participants