IAM-10: passwortlose-anmeldung-via-webauthn-passkey

internal/webauthn: vereinfachte, aber kryptographisch echte Challenge-
Response-Zeremonie (Ed25519) statt des vollstaendigen W3C-WebAuthn-
Drahtformats (CBOR-attestationObject/COSE), das ohne Browser-Umgebung hier
nicht erzeugt/geprueft werden kann (siehe Paket-Dokumentation, analoge
Einschraenkung wie IAM-05/IAM-06). Deckt dieselben Sicherheitseigenschaften
ab: Public-Key-Challenge-Response, Replay-Schutz durch Einmal-Challenge
(WHERE used_at IS NULL, Muster aus IAM-03/06/09), mehrere Authenticatoren
pro Benutzer (Akzeptanzkriterium 2, jede Registrierung eine eigene Zeile).

CompleteLogin komponiert auth.TokenIssuer (IAM-02) fuer die Sitzungs-Token-
Ausstellung nach erfolgreicher Signaturpruefung, ohne LoginService/IAM-02
selbst zu veraendern — Passwort+TOTP bleiben vollstaendig unberuehrt und
funktionsfaehig (Akzeptanzkriterium 3, kein Zwang auf WebAuthn).

Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS):
1. Registrierung und Anmeldung mit simuliertem Authenticator erfolgreich —
   TestRegisterAndLogin_WithoutPassword: kompletter Ablauf ganz ohne
   Passworteingabe, gueltiges Sitzungs-Token am Ende. PASS.
2. Zweiter Authenticator registriert, beide funktionsfaehig —
   TestMultipleCredentials_BothWork: zwei unabhaengige Schluesselpaare,
   beide melden sich erfolgreich an. PASS.
3. Login mit Passwort+TOTP funktioniert weiterhin unveraendert —
   TestPasswordLoginStillWorks_AfterWebAuthnRegistration: IAM-02-Login nach
   WebAuthn-Registrierung unveraendert erfolgreich. PASS.

Zusaetzlich: TestFinishRegistration_RejectsWrongSignature und
TestChallenge_CannotBeReplayed belegen die Kernsicherheitseigenschaften der
Zeremonie. PASS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-08-27 23:05:42 +02:00
co-authored by Claude Sonnet 5
parent 3d20d86a4f
commit ba71bb6350
7 changed files with 484 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
package webauthn
import (
"context"
"gitea.perlbach24.de/scripte/nexarch/internal/auth"
)
// CompleteLogin verifiziert die WebAuthn-Signatur und stellt bei Erfolg ein
// normales IAM-02-Sitzungs-Token aus — komponiert auth.TokenIssuer, ohne
// LoginService/IAM-02 selbst zu veraendern. Passwort+TOTP (IAM-02/IAM-04)
// bleiben davon vollstaendig unberuehrt und weiterhin nutzbar
// (Akzeptanzkriterium 3).
func CompleteLogin(ctx context.Context, store *Store, issuer *auth.TokenIssuer, tenantSlug, userID, challenge, credentialID string, signature []byte) (token string, err error) {
if err := store.FinishLogin(ctx, userID, challenge, credentialID, signature); err != nil {
return "", err
}
return issuer.Issue(userID, tenantSlug)
}