test(e2e): a medewerker login must not reuse a spent TOTP counter (refs #132)

Two beheer specs log in as bram-beheerder back to back, so both submit the
code for the same 30-second counter. Keycloak's otpPolicyCodeReusable
defaults to false, so it refuses the second one as invalid credentials and
the beheer portal never loads — which is how verify-e2e went red on #158.

Pins the counter choice as a pure function of "now" and the last counter
this medewerker spent, so the guard is checkable without a browser.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
not
2026-09-04 09:53:55 +02:00
co-authored by Claude Opus 5
parent a87a32e269
commit 716b8d03e0
+14
View File
@@ -0,0 +1,14 @@
import { expect, test } from '@playwright/test';
import { OTP_PERIOD_MS, nextUnusedCounter } from './medewerker-login';
// Pure check of the TOTP counter guard in loginMedewerker — no browser, no stack. Keycloak refuses
// a code it has already accepted (its otpPolicyCodeReusable defaults to false), so two logins as
// the same medewerker inside one 30-second window must not spend the same counter twice (#132).
test('a login never spends a TOTP counter this medewerker already used', () => {
const now = 3 * OTP_PERIOD_MS + 1_000; // 1 second into counter 3
expect(nextUnusedCounter(now, -1)).toBe(3); // nothing spent yet → the current counter
expect(nextUnusedCounter(now, 3)).toBe(4); // the current counter is spent → the next one
expect(nextUnusedCounter(now, 4)).toBe(5); // two logins already in this window → the one after
expect(nextUnusedCounter(now + OTP_PERIOD_MS, 3)).toBe(4); // window moved on → current again
});