Implement Strong Password Validation with Character and Length Requirements#172
Conversation
|
@anushreekhatri028-coder is attempting to deploy a commit to the Kunal Verma's projects Team on Vercel. A member of the Team first needs to authorize it. |
🚀 PR Received SuccessfullyHello @anushreekhatri028-coder, Thank you for taking the initiative to contribute to this project. Please ensure that your PR follows all project guidelines properly before requesting review.
|
📝 WalkthroughWalkthroughPassword validation is strengthened across signup and password-reset flows to enforce 8+ characters plus uppercase, lowercase, numeric, and special character requirements. Validation logic, error messages, and UI constraints are updated in both ChangesPassword Strength Requirements
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📋 Issue PlannerLet us write the prompt for your AI agent so you can ship faster (with fewer bugs). View plan for ticket: ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/pages/SignupPage.jsx (1)
77-77:⚠️ Potential issue | 🟠 MajorBackend doesn’t enforce the same password complexity policy as the client
server/modules/auth/validation.jsonly enforcespassword/newPasswordasz.string().min(6)(no min length of 8 and no uppercase/lowercase/numeric/special checks).server/modules/auth/service.jshashes the password directly withbcrypt.hash(...)and does not add any complexity validation.server/models/User.jsalso only setspasswordminlength: 6.Align backend validation for both signup and reset to the exact client requirements to prevent client-side bypasses.
🤖 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 `@frontend/src/pages/SignupPage.jsx` at line 77, The backend currently only enforces minlength 6 and hashes passwords without matching the client's complexity policy; update the auth validation schema(s) in validation.js (the password and newPassword fields used for signup/reset) to require a minimum length of 8 plus a regex check for uppercase, lowercase, numeric and special characters (mirror the client policy), ensure auth service (service.js) runs these validators before calling bcrypt.hash(...) for register/reset handlers, and update the User model's password field (e.g., password schema/minlength/validate in User.js) to minlength: 8 and/or the same regex validator so the model, validation layer, and service logic all enforce identical complexity.
🧹 Nitpick comments (3)
frontend/src/components/auth/ForgotPassword.jsx (2)
100-100: ⚡ Quick winConsider trimming password to prevent accidental whitespace.
Passwords with leading or trailing whitespace (e.g.,
"Abc123! ") pass validation and are sent to the backend as-is. If users accidentally include spaces, they may be unable to log in later if they omit them. Consider trimming the password in theonChangehandler or before submission to prevent this.🔧 Trim password on change
value={newPassword} id="new-password" - onChange={(e) => setNewPassword(e.target.value)} + onChange={(e) => setNewPassword(e.target.value.trim())} className="w-full p-5 border-4 border-black rounded-none text-black font-bold focus:outline-none focus:ring-0 focus:border-gray-500"🤖 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 `@frontend/src/components/auth/ForgotPassword.jsx` at line 100, The reset flow currently sends newPassword as-is to authService.resetPassword (call at await authService.resetPassword(email.trim(), normalizedOtp, newPassword)); trim the password to avoid accidental leading/trailing whitespace by replacing usages of newPassword with a trimmed value before submission (e.g., derive const trimmedPassword = newPassword.trim() and pass that to authService.resetPassword) or trim in the password input onChange handler so the component state always contains trimmed passwords.
283-289: ⚡ Quick winReplace static checklist with dynamic requirement feedback.
The checklist always displays checkmarks regardless of whether the password meets each requirement. This misleads users about which criteria are actually satisfied. SignupPage implements dynamic feedback (lines 221-227) that shows ✓ or ✗ based on the current password state—the same pattern should be used here for consistency and better UX.
Additionally, consider adding
aria-live="polite"to announce requirement changes to screen reader users.♻️ Refactor to match SignupPage's dynamic checklist
First, compute individual checks similar to SignupPage:
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,}$/; - const isPasswordValid = passwordRegex.test(newPassword); + const passwordChecks = { + length: newPassword.length >= 8, + uppercase: /[A-Z]/.test(newPassword), + lowercase: /[a-z]/.test(newPassword), + number: /\d/.test(newPassword), + special: /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(newPassword), + }; + const isPasswordValid = Object.values(passwordChecks).every(Boolean); const isOtpValid = otp.trim().length === 6;Then update the checklist to show dynamic feedback:
- <div className="text-xs text-gray-600 space-y-1"> - <p>✓ Minimum 8 characters</p> - <p>✓ One uppercase letter (A-Z)</p> - <p>✓ One lowercase letter (a-z)</p> - <p>✓ One number (0-9)</p> - <p>✓ One special character (!@#$%^&*)</p> - </div> + <ul className="text-xs font-bold space-y-1 text-gray-600" aria-live="polite"> + <li>{passwordChecks.length ? "✓" : "✗"} Minimum 8 characters</li> + <li>{passwordChecks.uppercase ? "✓" : "✗"} One uppercase letter (A-Z)</li> + <li>{passwordChecks.lowercase ? "✓" : "✗"} One lowercase letter (a-z)</li> + <li>{passwordChecks.number ? "✓" : "✗"} One number (0-9)</li> + <li>{passwordChecks.special ? "✓" : "✗"} One special character (!@#$%^&*)</li> + </ul>🤖 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 `@frontend/src/components/auth/ForgotPassword.jsx` around lines 283 - 289, The static checklist in ForgotPassword.jsx currently always shows checkmarks; change it to compute per-requirement booleans (e.g., isMinLength, hasUppercase, hasLowercase, hasNumber, hasSpecial) from the current password value (same approach used in SignupPage around lines 221-227) and render each line with a conditional ✓ or ✗ based on those booleans instead of hardcoded ticks; also add aria-live="polite" to the checklist container (the div with class "text-xs text-gray-600 space-y-1") so screen readers announce updates.frontend/src/pages/SignupPage.jsx (1)
221-227: ⚡ Quick winAdd
aria-liveto announce requirement changes to screen readers.The dynamic checklist provides excellent visual feedback, but screen reader users must manually re-read the list after each keystroke to check if requirements are met. Adding
aria-live="polite"will announce changes automatically, improving accessibility.♿ Add aria-live for accessibility
- <ul className="text-xs font-bold space-y-1 text-gray-600"> + <ul className="text-xs font-bold space-y-1 text-gray-600" aria-live="polite"> <li>{passwordChecks.length ? "✓" : "✗"} Minimum 8 characters</li> <li>{passwordChecks.uppercase ? "✓" : "✗"} One uppercase letter</li> <li>{passwordChecks.lowercase ? "✓" : "✗"} One lowercase letter</li> <li>{passwordChecks.number ? "✓" : "✗"} One number</li> <li>{passwordChecks.special ? "✓" : "✗"} One special character</li> </ul>🤖 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 `@frontend/src/pages/SignupPage.jsx` around lines 221 - 227, The password requirements checklist (the <ul> rendering passwordChecks in SignupPage.jsx) is dynamic but not announced to screen readers; add an ARIA live region so changes are spoken: wrap or update the checklist element that uses passwordChecks (the <ul> showing Minimum 8 characters, One uppercase letter, etc.) with aria-live="polite" (and optionally aria-atomic="true") so screen readers automatically announce requirement state changes as the user types.
🤖 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.
Outside diff comments:
In `@frontend/src/pages/SignupPage.jsx`:
- Line 77: The backend currently only enforces minlength 6 and hashes passwords
without matching the client's complexity policy; update the auth validation
schema(s) in validation.js (the password and newPassword fields used for
signup/reset) to require a minimum length of 8 plus a regex check for uppercase,
lowercase, numeric and special characters (mirror the client policy), ensure
auth service (service.js) runs these validators before calling bcrypt.hash(...)
for register/reset handlers, and update the User model's password field (e.g.,
password schema/minlength/validate in User.js) to minlength: 8 and/or the same
regex validator so the model, validation layer, and service logic all enforce
identical complexity.
---
Nitpick comments:
In `@frontend/src/components/auth/ForgotPassword.jsx`:
- Line 100: The reset flow currently sends newPassword as-is to
authService.resetPassword (call at await authService.resetPassword(email.trim(),
normalizedOtp, newPassword)); trim the password to avoid accidental
leading/trailing whitespace by replacing usages of newPassword with a trimmed
value before submission (e.g., derive const trimmedPassword = newPassword.trim()
and pass that to authService.resetPassword) or trim in the password input
onChange handler so the component state always contains trimmed passwords.
- Around line 283-289: The static checklist in ForgotPassword.jsx currently
always shows checkmarks; change it to compute per-requirement booleans (e.g.,
isMinLength, hasUppercase, hasLowercase, hasNumber, hasSpecial) from the current
password value (same approach used in SignupPage around lines 221-227) and
render each line with a conditional ✓ or ✗ based on those booleans instead of
hardcoded ticks; also add aria-live="polite" to the checklist container (the div
with class "text-xs text-gray-600 space-y-1") so screen readers announce
updates.
In `@frontend/src/pages/SignupPage.jsx`:
- Around line 221-227: The password requirements checklist (the <ul> rendering
passwordChecks in SignupPage.jsx) is dynamic but not announced to screen
readers; add an ARIA live region so changes are spoken: wrap or update the
checklist element that uses passwordChecks (the <ul> showing Minimum 8
characters, One uppercase letter, etc.) with aria-live="polite" (and optionally
aria-atomic="true") so screen readers automatically announce requirement state
changes as the user types.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 813de9b6-1e57-40ba-bbad-899c32b894bf
📒 Files selected for processing (2)
frontend/src/components/auth/ForgotPassword.jsxfrontend/src/pages/SignupPage.jsx
Related Issue
Closes #167
Description
Implemented strong password validation across user authentication flows to improve account security and prevent the use of weak passwords.
Changes Made
Motivation
Previously, users could create accounts or reset passwords using weak passwords such as
password,12345678, orabc123. This increased the risk of unauthorized account access and weakened overall platform security.These changes enforce stronger password policies, improve user guidance during registration and password reset, and enhance account protection.
Type of Change
Testing
Verification
Test Details
Verified password validation during user registration and password reset workflows.
Tested the following scenarios:
Rejected Passwords
* password
* 12345678
* abc123
* Password123
* PASSWORD@123
Accepted Passwords
* Password@123
* StrongPass#2026
* CodeLens!123
Verified that:
Checklist
Additional Notes
The validation logic has been implemented consistently across signup and password reset flows to ensure uniform password security requirements throughout the application.
Backend validation should also enforce the same password policy to prevent bypassing client-side checks.
Summary by CodeRabbit
New Features
Improvements