fix(auth): Einmalkennwoerter nicht zweimal annehmen
Ein TOTP-Code blieb rund 90 Sekunden gueltig und liess sich darin beliebig oft verwenden. RFC 6238 verlangt in Abschnitt 5.2 ausdruecklich das Gegenteil: derselbe Code darf kein zweites Mal angenommen werden. Ohne diese Sperre kann ein abgefangener Code - ueber die Schulter gesehen, von einer weiterleitenden Phishing-Seite, von Schadsoftware vom Bildschirm gelesen - die restliche Gueltigkeitsdauer ueber wiederverwendet werden. verifyTotp gibt dafuer jetzt ueber matchTotp das Zeitfenster zurueck, das gepasst hat; angenommen wird nur, was neuer ist als das zuletzt eingeloeste. Der Vergleich bleibt dabei in konstanter Zeit - es wird weiterhin nicht fruehzeitig abgebrochen. Auch die Aktivierung verbrennt ihr Fenster: der Code, der eben scharfgeschaltet hat, soll nicht Sekunden spaeter noch zum Anmelden taugen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,6 +75,8 @@ export interface PendingLoginState {
|
||||
isActive: boolean;
|
||||
/** Entschluesselter TOTP-Schluessel; null, wenn er nicht lesbar ist. */
|
||||
totpSecret: string | null;
|
||||
/** Zuletzt eingeloestes Zeitfenster – gegen die Wiederverwendung. */
|
||||
totpLastCounter: number | null;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -104,6 +106,7 @@ export async function readPendingLogin(): Promise<PendingLoginState | null> {
|
||||
role: pending.user.role,
|
||||
isActive: pending.user.isActive,
|
||||
totpSecret: tryDecryptSecret(pending.user.totpSecretCipher),
|
||||
totpLastCounter: pending.user.totpLastCounter,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user