# Password Reset ## Endpoints ### `POST /api/v1/auth/forgot-password` Request: ```json { "data": { "type": "auth_forgot_password", "attributes": { "email": "user@example.com" } } } ``` Response (`200` always for valid payload): ```json { "data": { "type": "auth_forgot_password", "attributes": { "message": "If the account exists, a password reset link has been sent." } } } ``` ### `POST /api/v1/auth/reset-password` Request: ```json { "data": { "type": "auth_reset_password", "attributes": { "token": "", "new_password": "StrongPassphrase123!", "confirm_password": "StrongPassphrase123!" } } } ``` Success response (`200`): ```json { "data": { "type": "auth_reset_password", "attributes": { "message": "Password has been reset successfully. Please log in again." } } } ``` Invalid/expired/used token response (`400`): ```json { "errors": [ { "status": "400", "title": "Invalid reset link", "detail": "This reset link is invalid or expired." } ] } ``` ## Environment Variables - `AUTH_PASSWORD_RESET_URL` frontend reset page URL; backend appends `?token=...` - `AUTH_PASSWORD_RESET_TTL` reset token TTL (default `20m`, enforced 15-30m range) - `AUTH_FORGOT_PASSWORD_EMAIL_COOLDOWN` cooldown per email identifier (default `2m`) - `AUTH_FORGOT_PASSWORD_MIN_DURATION` minimum forgot-password response duration (default `150ms`) - `AUTH_FORGOT_PASSWORD_IP_RATE_MAX` per-IP max attempts in window (default `10`) - `AUTH_FORGOT_PASSWORD_IP_RATE_WINDOW` per-IP window duration (default `15m`) ## Security Decisions - Uses `crypto/rand` for reset token entropy. - Stores only SHA-256 token hashes in DB (`password_reset_tokens.token_hash`). - Raw token is only delivered via email link. - Tokens are single-use (`used_at`) and expire (`expires_at`). - New forgot-password request invalidates previous active reset tokens for that user. - Successful reset invalidates all active reset tokens for the user. - Successful reset revokes active sessions by incrementing the MySQL-backed user session version used in JWT claims. - Forgot-password response is generic to prevent account enumeration. - Forgot-password throttling is applied per IP and per email identifier.