dak.c2s/docs/plans/2026-02-28-password-reset-design.md
CCS Admin d5db84d93f feat: add self-service password reset via email
Adds "Passwort vergessen?" to login page with email-based password
reset flow. Backend generates secure token (SHA-256 hashed, 1h expiry),
sends reset link via SMTP, and validates on submission. Includes rate
limiting (3 requests/hour/email), audit logging, and account unlock
on successful reset. New ResetPasswordPage with password confirmation.

New DB table: password_reset_tokens (migration 008).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:56:07 +00:00

2 KiB

Passwort-Reset per E-Mail — Design

Flow

  1. Nutzer klickt "Passwort vergessen?" auf der Login-Seite
  2. Gibt E-Mail-Adresse ein → POST /api/auth/forgot-password
  3. Backend generiert Token, speichert Hash in DB, sendet E-Mail mit Link
  4. E-Mail enthält: {FRONTEND_BASE_URL}/reset-password?token=XXX (1h gültig)
  5. Nutzer klickt Link → Frontend zeigt "Neues Passwort"-Formular
  6. Nutzer gibt neues Passwort ein → POST /api/auth/reset-password
  7. Backend validiert Token, setzt Passwort, invalidiert Token

Backend

Neues Modell: PasswordResetToken

Felder: id, user_id (FK), token_hash (SHA-256), expires_at (1h), used_at, created_at.

Endpoints

  • POST /api/auth/forgot-password — Immer 200 (verhindert User-Enumeration). Bei gültiger E-Mail: Token generieren, E-Mail senden.
  • POST /api/auth/reset-password — Token + neues Passwort. Validiert Token, setzt Passwort, invalidiert alle Reset-Tokens des Users.

Config

FRONTEND_BASE_URL in Settings für Reset-Link-Generierung.

Sicherheit

  • Token: secrets.token_urlsafe(32), gespeichert als SHA-256 Hash
  • 1h gültig, einmalig verwendbar
  • Rate-Limiting: Max 3 Requests pro E-Mail pro Stunde
  • Funktioniert auch bei gesperrten Accounts
  • Audit-Log: password_reset_requested, password_reset_completed

Frontend

  • "Passwort vergessen?"-Link auf LoginPage
  • Inline E-Mail-Eingabe unter dem Login-Formular
  • Neue Route /reset-passwordResetPasswordPage.tsx
  • Formular: Neues Passwort + Bestätigung (min. 8 Zeichen)

Dateien

Datei Änderung
backend/app/models/user.py PasswordResetToken Modell
backend/alembic/versions/007_password_reset_tokens.py Migration
backend/app/config.py FRONTEND_BASE_URL Setting
backend/app/api/auth.py Zwei neue Endpoints
frontend/src/pages/LoginPage.tsx "Passwort vergessen?" UI
frontend/src/pages/ResetPasswordPage.tsx Neue Seite
frontend/src/App.tsx Route /reset-password