Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 297 additions & 0 deletions DEMO_APP_CHANGES_REQUIRED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
# Demo App Changes Required for Password Validation Fixes

This document outlines the changes needed in the SpringUserFrameworkDemoApp to work with the password validation security fixes.

---

## Critical Changes (Required for Password Reset to Work)

### 1. Fix Password Reset Form Action
**Status:** ❌ BROKEN - Password reset doesn't work
**Priority:** CRITICAL
**Impact:** Password reset flow is currently non-functional

#### Issue
The forgot-password-change form posts to the wrong endpoint:
- **Current:** Form posts to `/user/resetPassword` (which only sends email)
- **Expected:** Form posts to `/user/savePassword` (new endpoint that saves password)

#### Files to Change

**File:** `SpringUserFrameworkDemoApp/src/main/resources/templates/user/forgot-password-change.html`

**Line 25:** Change form action
```html
<!-- BEFORE -->
<form id="resetPasswordForm" th:action="@{/user/resetPassword}" method="POST">

<!-- AFTER -->
<form id="resetPasswordForm" th:action="@{/user/savePassword}" method="POST">
```

#### Field Name Validation
The current field names are CORRECT and match the new SavePasswordDto:
- ✅ `name="newPassword"` matches `SavePasswordDto.newPassword`
- ✅ `name="token"` matches `SavePasswordDto.token`
- ✅ `id="matchPassword"` is client-side only (not sent to server, which is correct)

The JavaScript sends `confirmPassword` in the payload, which needs to be added to the form:

**Line 33:** Add name attribute to confirmPassword field
```html
<!-- BEFORE -->
<input type="password" id="matchPassword" class="form-control" required>

<!-- AFTER -->
<input type="password" id="matchPassword" name="confirmPassword" class="form-control" required>
```

---

## Optional Improvements (Non-Breaking, Enhances UX)

### 2. Update Password Field Name Mismatch
**Status:** ⚠️ WORKING but inconsistent
**Priority:** MEDIUM
**Impact:** Update password works, but field names don't match backend DTO

#### Issue
The update-password form uses `currentPassword` but the backend expects `oldPassword`:

**JavaScript sends:**
```javascript
{
currentPassword: "...", // ❌ This field name
newPassword: "...",
confirmPassword: "..."
}
```

**Backend PasswordDto expects:**
```java
private String oldPassword; // ✅ This field name
private String newPassword;
```

**However:** This currently WORKS because Spring's model binding is lenient and maps it correctly, but it's inconsistent.

#### Recommended Fix (Optional)

**File:** `SpringUserFrameworkDemoApp/src/main/resources/static/js/user/update-password.js`

**Lines 27-31:** Update field name
```javascript
// BEFORE
const requestData = {
currentPassword: currentPassword,
newPassword: newPassword,
confirmPassword: confirmPassword,
};

// AFTER
const requestData = {
oldPassword: currentPassword, // Changed to match backend DTO
newPassword: newPassword,
};
// Note: confirmPassword removed - not needed by backend
```

**Alternative:** Keep it as-is since it's working. The inconsistency is minor.

---

## Enhanced User Experience Changes

### 3. Add Password Strength Meter to Other Forms
**Status:** ℹ️ Enhancement (Partial - only on registration)
**Priority:** LOW
**Impact:** Users get better feedback on password requirements

#### Current State
The Demo App already has a password strength meter on the **registration form** (`register.js`):
- ✅ Real-time strength calculation (Very Weak → Very Strong)
- ✅ Visual progress bar with color coding
- ✅ Password requirements checklist
- ✅ Checks for length, uppercase, lowercase, digits, special chars

**Files with existing implementation:**
- `src/main/resources/static/js/user/register.js` (lines 49-188)
- `src/main/resources/templates/user/register.html`

#### Enhancement Opportunity
Reuse the existing password strength meter code on:
1. **Password reset form** (`forgot-password-change.html`)
2. **Update password form** (`update-password.html`)

**Implementation Steps:**
1. Extract `calculateStrength()` and `updateStrengthBar()` functions to a shared module:
- Create: `static/js/utils/password-validation.js`
- Export functions for reuse

2. Add strength meter UI to other password forms:
- Modify: `templates/user/forgot-password-change.html`
- Modify: `templates/user/update-password.html`
- Import and use the shared password validation module

3. Add password requirements checklist to both forms:
```html
<div id="password-requirements" class="small text-muted mt-2 d-none">
<div>Password must contain:</div>
<div>• At least 8 characters</div>
<div>• An uppercase letter (A-Z)</div>
<div>• A lowercase letter (a-z)</div>
<div>• A number (0-9)</div>
<div>• A special character</div>
</div>
```

**Estimated Effort:** 1-2 hours (much less than creating from scratch)

**Note:** This is a UX enhancement and not required for functionality. The backend validation already enforces all rules.

---

## Testing Checklist

After making the required changes, test these scenarios:

### Password Reset Flow (Critical)
- [ ] Request password reset email
- [ ] Click link in email (opens forgot-password-change.html)
- [ ] Enter weak password (too short)
- Expected: Error message about password requirements
- [ ] Enter password that matches old password
- Expected: Error message about password history
- [ ] Enter valid strong password
- Expected: Success message, redirected to login
- [ ] Log in with new password
- Expected: Login succeeds
- [ ] Try to reuse the reset token
- Expected: Error - token already used/invalid

### Update Password Flow (Should Continue Working)
- [ ] Log in as existing user
- [ ] Navigate to update-password page
- [ ] Enter wrong old password
- Expected: Error "The old password is incorrect" (error code 1)
- [ ] Enter correct old password but weak new password
- Expected: Error about password requirements (error code 2)
- [ ] Enter correct old password and password from history
- Expected: Error about password reuse (error code 2)
- [ ] Enter correct old password and valid new password
- Expected: Success message
- [ ] Log out and log in with new password
- Expected: Login succeeds

### Registration Flow (Should Continue Working)
- [ ] Register new user with weak password
- Expected: Error message about password requirements
- [ ] Register new user with strong password
- Expected: Success, email sent (if verification enabled)

---

## Implementation Priority

### Phase 1: Critical Fix (Must Do Now)
1. **Fix password reset form action** (5 minutes)
- Change form action to `/user/savePassword`
- Add `name="confirmPassword"` to match password field
- Test password reset flow end-to-end

### Phase 2: Optional Consistency (Do Later)
2. **Fix field name inconsistency** (5 minutes)
- Update `update-password.js` to use `oldPassword` instead of `currentPassword`
- Test update password flow

### Phase 3: UX Enhancement (Nice to Have)
3. **Reuse password strength meter on other forms** (1-2 hours)
- Extract existing meter code to shared module
- Add to password reset and update password forms
- Note: Registration already has this implemented

---

## Code Changes Summary

### Required Changes (1 file, 2 lines)
```diff
File: SpringUserFrameworkDemoApp/src/main/resources/templates/user/forgot-password-change.html

-<form id="resetPasswordForm" th:action="@{/user/resetPassword}" method="POST">
+<form id="resetPasswordForm" th:action="@{/user/savePassword}" method="POST">

-<input type="password" id="matchPassword" class="form-control" required>
+<input type="password" id="matchPassword" name="confirmPassword" class="form-control" required>
```

### Optional Changes (1 file, 5 lines)
```diff
File: SpringUserFrameworkDemoApp/src/main/resources/static/js/user/update-password.js

const requestData = {
- currentPassword: currentPassword,
+ oldPassword: currentPassword,
newPassword: newPassword,
- confirmPassword: confirmPassword,
};
```

---

## Validation Reference

### Backend Password Policy (Configured in Framework)
These rules are enforced by the backend `PasswordPolicyService`:

```properties
user.security.password.enabled=true
user.security.password.min-length=8
user.security.password.max-length=128
user.security.password.require-uppercase=true
user.security.password.require-lowercase=true
user.security.password.require-digit=true
user.security.password.require-special=true
user.security.password.special-chars=~`!@#$%^&*()_-+={}[]|\:;"'<>,.?/
user.security.password.prevent-common-passwords=true
user.security.password.history-count=3
user.security.password.similarity-threshold=70
```

### Error Messages (Now Available)
New message keys added to framework:
- `message.password.mismatch` - "Passwords do not match."
- `message.reset-password.success` - "Your password has been successfully reset. You can now log in with your new password."

Existing message keys:
- `TOO_SHORT`, `TOO_LONG`, `INSUFFICIENT_UPPERCASE`, etc.
- `password.error.history.reuse` - "You cannot reuse your last {0} passwords."
- `password.error.similarity` - "Password is too similar to your username or email ({0}% similarity)."

---

## Backward Compatibility

All changes are backward compatible:
- ✅ Existing `/user/resetPassword` endpoint still works (sends email)
- ✅ New `/user/savePassword` endpoint is additive
- ✅ Existing `/user/updatePassword` endpoint enhanced with validation
- ✅ No breaking changes to existing APIs
- ✅ No database schema changes

The only "breaking" change is that the Demo App's password reset flow was already non-functional (form posted to wrong endpoint), so fixing it improves rather than breaks functionality.

---

## Questions?

If you have questions about these changes:
1. See [IMPLEMENTATION_PLAN_PASSWORD_FIXES.md](IMPLEMENTATION_PLAN_PASSWORD_FIXES.md) for detailed context
2. Review the code review findings that led to these fixes
3. Test the changes in a development environment first

---

**Last Updated:** 2025-01-26
**Framework Version:** 3.5.1-SNAPSHOT
**Related Branch:** feature/password-validation-fixes
Loading