b6a941feecbfa264ccaac1254d1b5eca5e65dd91
internal/authtoken: Einmal-Token fuer Passwort-Reset und Einladung, getrennt von internal/auth (Sessions/JWT), da der Vorgang bewusst session-los ist. Store.Create gibt das Klartext-Token NUR an den Aufrufer zurueck (fuer E-Mail-Versand, IAM-08), gespeichert wird ausschliesslich der SHA-256-Hash. Store.Consume markiert ein Token atomar als verwendet (UPDATE ... WHERE used_at IS NULL AND expires_at > now() RETURNING user_id) — Wiederverwendung und Ablauf werden serverseitig in derselben Datenbankoperation durchgesetzt, kein Race zwischen Pruefen und Verbrauchen moeglich. Ungueltig, bereits verwendet und abgelaufen liefern denselben ErrInvalidToken (Akzeptanz- kriterium 3), damit die Antwort keinen der drei Faelle verraet. CompletePasswordReset/CompleteInvitation loesen ein Token ein und setzen das Passwort ueber user.TenantUserStore.SetPasswordHash (IAM-01) — keine Auth-Middleware, keine Session noetig (Akzeptanzkriterium 2). Log-Statements bei Create/Consume enthalten bewusst nur user_id/purpose, niemals das Token selbst. Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS): 1. Wiederverwendung eines bereits eingeloesten Tokens automatisiert abgewiesen — TestConsume_RejectsReuse. PASS. 2. Ablaufzeit serverseitig durchgesetzt — TestConsume_RejectsExpiredToken (Token mit negativer TTL sofort abgelaufen). PASS. 3. Token werden nicht im Klartext geloggt (Stichprobe im Log-Ausgang) — TestCreateAndConsume_NeverLogTokenPlaintext: Log-Buffer nach Create + ungueltigem + gueltigem Consume enthaelt das Klartext-Token nachweislich nicht. PASS. Zusaetzlich: TestCompleteInvitation_SetsPasswordWithoutSession belegt Akzeptanzkriterium 2 konkret (Passwort gesetzt und verifizierbar, keine Session im Ablauf beteiligt). PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The file is empty.
Languages
Go
100%