Bisher prüfte der Re-Auth-Trigger nur den Host – `https://1und1.de/foo`
→ `https://1und1.de/phishing/path` ging ohne currentPassword durch.
Damit konnte ein gestohlener JWT Phishing-Pfade auf trusted Domains
plazieren.
Backend (provider.controller): normalizeUrlForCompare vergleicht
jetzt die komplette URL (Trailing-Slash, Whitespace, Case),
nicht nur den Host. hostOf-Helper entfernt.
Frontend (ProviderModal): gleiche Normalisierung im UI, damit der
Bestätigungs-Banner mit der Backend-Prüfung synchron läuft.
Banner-Text leicht angepasst (nicht mehr "Domain wurde geändert"
sondern generisch "Portal-URL wurde geändert").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
47.3 MEDIUM (Admin-Passwort-Reset ohne Re-Auth):
POST /api/users/:id/password verlangt jetzt currentPassword im
Body. Backend prüft per bcrypt.compare gegen den Hash des
aufrufenden Admins. Frontend (UserList-Modal): zusätzliches
Passwort-Feld wird eingeblendet, sobald für einen User ein neues
Passwort gesetzt werden soll. Gestohlener JWT allein reicht damit
nicht mehr.
47.1 MEDIUM (Open Redirect / Phishing via provider.portalUrl):
Selbes Re-Auth-Pattern für Provider-Endpoints. Nur wenn die
Portal-URL-Domain WIRKLICH gewechselt wird (Host-Vergleich)
oder beim Create mit URL, ist currentPassword Pflicht. Reine
Namens-/Tarif-Edits bleiben friction-frei.
Audit-Log bekommt die Portal-URL beim Ändern explizit mitgeloggt
(Forensik bei Vorfällen). Frontend ProviderModal zeigt amber-
farbenen Bestätigungs-Banner mit Passwort-Eingabe sobald der
Host wechselt.
47.2 INFO (provider.name ohne Backend-Sanitization):
Neuer Helper stripProviderStrings in provider.service, wendet
stripHtml auf name + usernameFieldName + passwordFieldName an –
Defense-in-Depth gegen neue Renderpfade (PDF, Mail-Templates).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>