400 lines
14 KiB
Markdown
400 lines
14 KiB
Markdown
# User Authentication UI Adaptations
|
|
|
|
## Overview
|
|
|
|
This document describes the necessary UI changes and adaptations required to implement the magic link-based user authentication process described in `doc_userauth_process_concept.md`.
|
|
|
|
**Last Updated**: Based on codebase analysis of current frontend implementation.
|
|
|
|
## Current Frontend State
|
|
|
|
### Existing Pages
|
|
1. **`frontend_agents/public/login.html`**
|
|
- Contains login form with username/password fields
|
|
- Has buttons for Microsoft and Google authentication
|
|
- Has registration link
|
|
- **Missing**: Password reset button
|
|
|
|
2. **`frontend_agents/public/register.html`**
|
|
- Contains registration form with:
|
|
- Username field
|
|
- Password field (required)
|
|
- Confirm password field (required)
|
|
- Email field
|
|
- Full name field
|
|
- Language selector
|
|
- **Needs modification**: Remove password fields, add email-only registration
|
|
|
|
3. **`frontend_agents/public/js/security/auth.js`**
|
|
- Contains `setupRegisterPage()` function
|
|
- Contains `validateRegistrationForm()` function that requires password
|
|
- Contains email validation logic
|
|
- **Needs modification**: Remove password validation, add shared email validation function
|
|
|
|
4. **`frontend_agents/public/js/shared/apiCalls.js`**
|
|
- Contains `register()` function that sends password
|
|
- **Missing**: Password reset request and reset password API calls
|
|
|
|
## Required UI Changes
|
|
|
|
### 1. Login Page (`frontend_agents/public/login.html`)
|
|
|
|
#### Changes Required:
|
|
- Add "Password Reset" button/link below the login form
|
|
- Button should link to `/password-reset-request.html`
|
|
- Style should match existing button styles (use `btn` class with appropriate variant)
|
|
|
|
#### Implementation:
|
|
```html
|
|
<!-- Add after login form, before register-options div -->
|
|
<div class="password-reset-link">
|
|
<a href="password-reset-request.html" class="btn btn-link">
|
|
<i class="fas fa-key"></i> Passwort zurücksetzen
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
#### Styling Considerations:
|
|
- Use existing CSS classes from `htmlparts/styles.css`
|
|
- Match styling with registration link
|
|
- Ensure responsive design matches login page layout
|
|
|
|
### 2. Registration Page (`frontend_agents/public/register.html`)
|
|
|
|
#### Changes Required:
|
|
- **Remove** password and confirm password fields
|
|
- **Keep** username, email, fullName, language fields
|
|
- Update form validation to not require password
|
|
- Update success message to indicate email will be sent
|
|
- Add spam folder reminder message
|
|
|
|
#### Implementation:
|
|
```html
|
|
<!-- Remove these fields: -->
|
|
<!-- <div class="login-form-group">
|
|
<label for="password">Passwort*</label>
|
|
<input type="password" id="password" name="password" required minlength="8">
|
|
<div class="field-error"></div>
|
|
</div>
|
|
<div class="login-form-group">
|
|
<label for="confirm-password">Passwort bestätigen*</label>
|
|
<input type="password" id="confirm-password" name="confirm-password" required>
|
|
<div class="field-error"></div>
|
|
</div> -->
|
|
|
|
<!-- Add info message after form: -->
|
|
<div class="registration-info">
|
|
<p>Nach der Registrierung erhalten Sie eine E-Mail mit einem Link zum Setzen Ihres Passworts.</p>
|
|
<p class="spam-reminder">Bitte prüfen Sie auch Ihren Spam-Ordner, falls Sie keine E-Mail erhalten.</p>
|
|
</div>
|
|
```
|
|
|
|
#### JavaScript Changes (`frontend_agents/public/js/security/auth.js`):
|
|
- Update `validateRegistrationForm()` to remove password validation
|
|
- Update `setupRegisterPage()` to handle no-password registration
|
|
- Create shared `validateEmailFormat()` function for reuse
|
|
|
|
### 3. New Page: Password Reset Request (`frontend_agents/public/password-reset-request.html`)
|
|
|
|
#### Purpose:
|
|
Allow users to request a password reset by entering their email address.
|
|
|
|
#### Structure:
|
|
- Similar layout to `register.html`
|
|
- Single email input field
|
|
- Submit button
|
|
- Link back to login page
|
|
- Success/error message area
|
|
|
|
#### Implementation:
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>PowerOn - Passwort zurücksetzen</title>
|
|
<link rel="stylesheet" href="./htmlparts/styles_variables.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles_base.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles_icons.css">
|
|
</head>
|
|
<body>
|
|
<div class="login-container">
|
|
<h1>Passwort zurücksetzen</h1>
|
|
<div id="reset-request-error" class="login-error-message"></div>
|
|
<form id="password-reset-request-form">
|
|
<div class="login-form-group">
|
|
<label for="email">E-Mail-Adresse*</label>
|
|
<input type="email" id="email" name="email" required autocomplete="email">
|
|
<div class="field-error"></div>
|
|
</div>
|
|
<button type="submit" class="btn btn-success login-btn">Reset-Link anfordern</button>
|
|
</form>
|
|
<div class="register-link">
|
|
<p>Zurück zum <a href="login.html">Login</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Benötigte globale Utilities -->
|
|
<script type="module" src="js/shared/utils.js"></script>
|
|
|
|
<!-- Module -->
|
|
<script type="module" src="js/security/passwordResetRequest.js"></script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### JavaScript Module (`frontend_agents/public/js/security/passwordResetRequest.js`):
|
|
- Handle form submission
|
|
- Validate email format using shared function from `auth.js`
|
|
- Call password reset request API
|
|
- Show generic success message
|
|
- Redirect to login page after showing message
|
|
|
|
### 4. New Page: Password Reset (`frontend_agents/public/reset.html`)
|
|
|
|
#### Purpose:
|
|
Allow users to set a new password using the token from the magic link.
|
|
|
|
#### Structure:
|
|
- Similar layout to `register.html`
|
|
- Password field (with strength indicator)
|
|
- Confirm password field
|
|
- Submit button
|
|
- Extract token from URL parameter (`?token=<UUID>`)
|
|
- Success/error message area
|
|
|
|
#### Implementation:
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>PowerOn - Neues Passwort setzen</title>
|
|
<link rel="stylesheet" href="./htmlparts/styles_variables.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles_base.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles.css">
|
|
<link rel="stylesheet" href="./htmlparts/styles_icons.css">
|
|
</head>
|
|
<body>
|
|
<div class="login-container">
|
|
<h1>Neues Passwort setzen</h1>
|
|
<div id="reset-error" class="login-error-message"></div>
|
|
<form id="reset-password-form">
|
|
<div class="login-form-group">
|
|
<label for="password">Neues Passwort*</label>
|
|
<input type="password" id="password" name="password" required minlength="8">
|
|
<div class="field-error"></div>
|
|
<small class="password-hint">Mindestens 8 Zeichen</small>
|
|
</div>
|
|
<div class="login-form-group">
|
|
<label for="confirm-password">Passwort bestätigen*</label>
|
|
<input type="password" id="confirm-password" name="confirm-password" required>
|
|
<div class="field-error"></div>
|
|
</div>
|
|
<button type="submit" class="btn btn-success login-btn">Passwort setzen</button>
|
|
</form>
|
|
<div class="register-link">
|
|
<p>Zurück zum <a href="login.html">Login</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Benötigte globale Utilities -->
|
|
<script type="module" src="js/shared/utils.js"></script>
|
|
|
|
<!-- Module -->
|
|
<script type="module" src="js/security/reset.js"></script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### JavaScript Module (`frontend_agents/public/js/security/reset.js`):
|
|
- Extract token from URL parameter
|
|
- Validate token format (UUID)
|
|
- Handle form submission
|
|
- Validate password strength (min 8 chars, match requirements from config)
|
|
- Validate password confirmation matches
|
|
- Call password reset API
|
|
- Show success message with spam folder reminder
|
|
- Redirect to login page after 3 seconds
|
|
|
|
### 5. API Calls (`frontend_agents/public/js/shared/apiCalls.js`)
|
|
|
|
#### New Functions Required:
|
|
|
|
1. **`requestPasswordReset(email)`**
|
|
```javascript
|
|
requestPasswordReset: async function(email) {
|
|
try {
|
|
return await privateApi.post('/api/local/password-reset-request', { email });
|
|
} catch (error) {
|
|
ui.log.error('Password reset request error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
2. **`resetPassword(token, password)`**
|
|
```javascript
|
|
resetPassword: async function(token, password) {
|
|
try {
|
|
return await privateApi.post('/api/local/password-reset', { token, password });
|
|
} catch (error) {
|
|
ui.log.error('Password reset error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
3. **Update `register()` function**
|
|
- Remove password from request body
|
|
- Update to handle new registration flow (no password required)
|
|
|
|
### 6. Shared Email Validation (`frontend_agents/public/js/security/auth.js`)
|
|
|
|
#### New Function:
|
|
```javascript
|
|
/**
|
|
* Validates email format
|
|
* @param {string} email - Email address to validate
|
|
* @returns {boolean} - True if valid, false otherwise
|
|
*/
|
|
export function validateEmailFormat(email) {
|
|
if (!email) return false;
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(email.trim());
|
|
}
|
|
```
|
|
|
|
#### Usage:
|
|
- Used by registration form
|
|
- Used by password reset request form
|
|
- Ensures consistent email validation across the application
|
|
|
|
## UI/UX Considerations
|
|
|
|
### Error Handling
|
|
|
|
1. **Registration Errors**:
|
|
- Username already exists → Show error on username field
|
|
- Email already exists → Show generic success (security: don't reveal email exists)
|
|
- Email sending fails → Show generic success (don't reveal email issues)
|
|
|
|
2. **Password Reset Request Errors**:
|
|
- Invalid email format → Show error on email field
|
|
- Email not found → Show generic success (security: don't reveal email doesn't exist)
|
|
- Rate limiting → Show error message
|
|
|
|
3. **Password Reset Errors**:
|
|
- Invalid/expired token → Show error message, link back to password reset request
|
|
- Password too weak → Show specific requirements
|
|
- Password mismatch → Show error on confirm password field
|
|
|
|
### Success Messages
|
|
|
|
1. **Registration Success**:
|
|
```
|
|
"Registrierung erfolgreich! Bitte prüfen Sie Ihre E-Mail, um Ihr Passwort zu setzen.
|
|
Falls Sie keine E-Mail erhalten, prüfen Sie bitte auch Ihren Spam-Ordner."
|
|
```
|
|
|
|
2. **Password Reset Request Success**:
|
|
```
|
|
"Falls ein Konto mit dieser E-Mail-Adresse existiert, wurde ein Reset-Link gesendet.
|
|
Bitte prüfen Sie Ihre E-Mail und auch Ihren Spam-Ordner."
|
|
```
|
|
|
|
3. **Password Reset Success**:
|
|
```
|
|
"Passwort erfolgreich gesetzt! Sie werden zum Login weitergeleitet..."
|
|
```
|
|
|
|
### Accessibility
|
|
|
|
- All form fields should have proper labels
|
|
- Error messages should be associated with form fields using ARIA attributes
|
|
- Success messages should be announced to screen readers
|
|
- Form validation should provide clear, actionable feedback
|
|
|
|
### Responsive Design
|
|
|
|
- All pages should work on mobile devices
|
|
- Form layouts should adapt to smaller screens
|
|
- Buttons should be appropriately sized for touch interfaces
|
|
- Error messages should be readable on all screen sizes
|
|
|
|
## Testing Checklist
|
|
|
|
### Registration Flow
|
|
- [ ] User can register without password
|
|
- [ ] Email validation works correctly
|
|
- [ ] Success message displays correctly
|
|
- [ ] Redirect to login works
|
|
- [ ] Error handling for duplicate username
|
|
- [ ] Error handling for duplicate email (should show generic success)
|
|
|
|
### Password Reset Request Flow
|
|
- [ ] User can access password reset request page from login
|
|
- [ ] Email validation works correctly
|
|
- [ ] Success message displays correctly
|
|
- [ ] Redirect to login works
|
|
- [ ] Error handling for invalid email format
|
|
- [ ] Error handling for rate limiting
|
|
|
|
### Password Reset Flow
|
|
- [ ] User can access reset page with valid token
|
|
- [ ] Token extraction from URL works
|
|
- [ ] Password validation works correctly
|
|
- [ ] Password confirmation validation works
|
|
- [ ] Success message displays correctly
|
|
- [ ] Redirect to login works after 3 seconds
|
|
- [ ] Error handling for invalid token
|
|
- [ ] Error handling for expired token
|
|
- [ ] Error handling for weak password
|
|
|
|
### Integration Testing
|
|
- [ ] End-to-end registration flow works
|
|
- [ ] End-to-end password reset flow works
|
|
- [ ] Email links work correctly
|
|
- [ ] Token expiration handling works
|
|
- [ ] Multiple reset requests invalidate old tokens
|
|
|
|
## Implementation Order
|
|
|
|
1. **Backend Changes First** (prerequisites):
|
|
- Add resetToken fields to UserInDB model
|
|
- Implement password reset endpoints
|
|
- Implement email sending functionality
|
|
|
|
2. **Frontend API Layer**:
|
|
- Add password reset API calls to `apiCalls.js`
|
|
- Update registration API call
|
|
|
|
3. **Frontend Pages**:
|
|
- Create `password-reset-request.html`
|
|
- Create `reset.html`
|
|
- Update `login.html` (add reset button)
|
|
- Update `register.html` (remove password fields)
|
|
|
|
4. **Frontend JavaScript**:
|
|
- Create `passwordResetRequest.js`
|
|
- Create `reset.js`
|
|
- Update `auth.js` (remove password validation, add email validation function)
|
|
- Update `register.js` if needed
|
|
|
|
5. **Testing**:
|
|
- Test each flow independently
|
|
- Test integration between frontend and backend
|
|
- Test error scenarios
|
|
- Test edge cases
|
|
|
|
## Notes
|
|
|
|
- All text should be in German to match existing UI (`login.html` uses German)
|
|
- CSS classes should match existing patterns from `htmlparts/styles.css`
|
|
- Form validation should use existing patterns from `auth.js`
|
|
- Error handling should use existing patterns from `auth.js` (showFieldError, clearFieldError)
|
|
- Success messages should use existing patterns (showSuccessMessage)
|
|
- API calls should use existing patterns from `apiCalls.js` (privateApi.post, handleResponse)
|