Awesome Testing

Markdown document

Podsumowanie sesji Codex

Lekcja 23: Automatyzacja two-factor authentication

Historical artifacts may name disposable training credentials and environments. Do not reuse credentials, target course systems, or execute archived prompts without authorization.

Podsumowanie sesji Codex

Zakres sesji

Sesja dotyczyła zaprojektowania, sprawdzenia na żywym API i wdrożenia testów two-factor authentication w checkpointcie l18. Punktem wyjścia był zielony suite 142 testów, ale wszystkie sześć operacji 2FA wskazanych przez aktualny Swagger pozostawało bez dedykowanej automatyzacji.

Zakres obejmował pełny cykl klienta używającego aplikacji uwierzytelniającej:

  • rozpoczęcie konfiguracji TOTP,
  • potwierdzenie konfiguracji kodem jednorazowym,
  • sprawdzenie statusu 2FA,
  • dwuetapowe logowanie kodem TOTP,
  • logowanie jednorazowym kodem odzyskiwania,
  • wymianę kodów odzyskiwania,
  • wyłączenie 2FA i powrót do zwykłego logowania hasłem.

Użytkownik poprosił najpierw o discovery, plan oraz proof of concept wykonany przez curl lub skrypt. Następnie zlecił profesjonalną implementację i pełną walidację testów. W trakcie pracy doprecyzował również granicę środowiska: testy klienckie 2FA mają działać wyłącznie w projekcie api przeciwko awesome.byst.re, bez wariantu trenerskiego lub stagingowego.

Prompty użyte w Codex

Prompt otwierający sesję określił oczekiwany tryb explore-first:

Chciałbym, żebyś pomógł mi otestować two-factor czy tam multi-factor MFA,
zazwyczaj to się nazywa w literaturze. Mam kilka endpointów, masz namiary na
backend, mamy projekt, chciałbym, żebyś pracował w 18. [...] chciałbym, żebyśmy
na początku zrobili jakiś taki discovery właśnie plan, opracowali. I chciałbym,
żebyś też zrobił proof of concept, że to zadziała. Możesz zobaczyć jakoś
cURL-em czy tam jakimś skryptem, czy to faktycznie działa, czy te testy mają
sens, więc zrób taką eksplorację tego feature'a. Chciałbym, żebyś też zrobił
discovery bibliotek, co nam może pomóc tutaj, czy w ogóle to jest możliwe do
zrobienia z takiego poziomu end-to-end, czy nie.

Po discovery użytkownik zlecił implementację:

Okay, now implement it, make it right, make it professional, and run the tests,
obviously, make sure they work.

Najważniejsza korekta środowiskowa brzmiała:

Zrób to dla środowiska awesome bez trenera, bo to są testy klienckie, więc
zgodnie z konwencją zróbmy tam. Widziałem, że testowałeś na obu środowiskach,
nie ma to sensu.

Co sprawdził Codex przed implementacją?

Codex zastosował repozytoryjny workflow api-testing-skill. Najpierw przeczytał bieżący l18/api-test-plan.md, sprawdził istniejące fixture, klientów HTTP, typy, helpery asercji i konwencję inicjalizowania klientów w test.beforeEach. Następnie porównał sześć operacji 2FA z bieżącym dokumentem /v3/api-docs.

Repozytoryjny api-docs.json okazał się nieaktualny: zawierał 42 operacje i nie opisywał 2FA. Dlatego źródłem kontraktu dla testów klienckich został live Swagger środowiska awesome.byst.re.

Dostępny kod backendu pozwolił potwierdzić parametry algorytmu: TOTP używa SHA-1, sześciu cyfr i 30-sekundowego kroku. Backend akceptuje sąsiednie okno czasowe, blokuje ponowne użycie zaakceptowanego TOTP, utrzymuje konfigurację przez 15 minut, challenge logowania przez 5 minut i generuje osiem kodów odzyskiwania.

Przed napisaniem regresji powstał osobny skrypt eksploracyjny scripts/explore-2fa-poc.sh. Skrypt tworzy jednorazowego użytkownika, wykonuje setup, confirm, logowanie TOTP, logowanie kodem odzyskiwania, rotację kodów, disable oraz główne negatywne przypadki. Wyniki wrażliwe są redagowane, a konto jest usuwane po zakończeniu. Po korekcie użytkownika proof of concept został uruchomiony ponownie wyłącznie dla awesome.byst.re i zakończył się sukcesem.

W discovery bibliotek wybrano otplib@13.5.0. Biblioteka pozwala jawnie ustawić algorytm, liczbę cyfr, okres oraz epoch, dzięki czemu generowanie kodów jest zgodne z backendem i pozostaje kontrolowane w testach TypeScript.

Co zaimplementował Codex?

Powstała kompletna warstwa wspierająca 2FA:

  • types/mfa.ts z typami requestów i odpowiedzi,
  • httpclients/mfa-client.ts z metodami dla wszystkich sześciu operacji,
  • support/totp.ts z generowaniem kodu dla bieżącego lub następnego kroku,
  • support/assertions/mfa.ts z asercjami sekretu, URI OTPAuth, PNG QR i kodów odzyskiwania,
  • fixtures/mfa-user.ts z izolowanym użytkownikiem po pełnym enrollmencie,
  • dokładnie przypięta zależność otplib@13.5.0.

Każda operacja otrzymała osobny spec w tests/api/users/2fa/:

  • status.get.spec.ts,
  • setup.post.spec.ts,
  • confirm.post.spec.ts,
  • signin.post.spec.ts,
  • recovery-codes.post.spec.ts,
  • disable.post.spec.ts.

Łącznie dodano 28 testów. Oprócz happy pathów sprawdzają one między innymi brakujące pola, brak JWT, setup przed confirm, ponowiony setup, błędny TOTP, replay TOTP, błędny kod odzyskiwania, zużyty challenge, rotację kodów i próbę zarządzania 2FA przed jego aktywacją.

Testy są pogrupowane według rosnących statusów HTTP i używają komentarzy given, when, then. Klienci HTTP są inicjalizowani w test.beforeEach. Każdy test stanowy posiada własnego generowanego użytkownika oraz cleanup przez right-to-be-forgotten.

Specy 2FA wyłączają trace Playwrighta, ponieważ odpowiedzi setup i confirm zawierają sekret enrollmentu oraz kody odzyskiwania. Dla przepływów stanowych ustawiono timeout 90 sekund: zdalne requesty są wolniejsze, a test replay świadomie czeka na następny 30-sekundowy krok TOTP.

Jakie korekty zostały zlecone po implementacji?

Pierwsza eksploracja porównywała zachowanie dwóch live deploymentów. Użytkownik słusznie doprecyzował, że są to testy klienckie i zgodnie z konwencją projektu powinny należeć wyłącznie do projektu api używającego awesome.byst.re.

Po tej korekcie sprawdzono całą nową warstwę pod kątem odwołań do aitesters, admin-api i API_ADMIN_BASE_URL. Żaden nowy klient, fixture, helper, spec ani skrypt regresyjny nie używa środowiska stagingowego. Skrypt PoC domyślnie wskazuje awesome.byst.re.

Pełne npm test nadal uruchamia także istniejący projekt admin-api, ponieważ jest to część wcześniejszej architektury l18. Nie dodano jednak żadnego testu 2FA do tego projektu.

Co wyszło w review?

Review potwierdziło, że API da się testować end-to-end bez aplikacji mobilnej. Sekret Base32 zwrócony przez endpoint setup wystarcza do wygenerowania tego samego TOTP, który utworzyłaby aplikacja typu authenticator. Dzięki temu test może sprawdzić cały protokół przez API.

W review wzmocniono test rotacji kodów odzyskiwania: nowy zestaw musi zawierać osiem unikalnych kodów i żaden z nich nie może wystąpić w starym zestawie. Poprawiono też asercję unikalności tak, aby używała wspieranego matchera.

Wykryto rozbieżność kontraktu. Pięć operacji 2FA publikuje DTO sukcesu jako schemat odpowiedzi błędnej, a POST /2fa/disable nie publikuje schematu błędu. Live API zwraca tymczasem mapę walidacyjną dla 400 oraz { "message": "..." } dla 401. Problem został opisany w bug-reports/2fa-openapi-error-schemas-use-success-dtos.md. Testy regresyjne asertują potwierdzone zachowanie runtime, ale nie uznają błędnego schematu OpenAPI za poprawny kontrakt.

Świadomie nie automatyzowano dwóch grup ścieżek: 410 po 15-minutowym wygaśnięciu setupu oraz 429 wymagających wyczerpania współdzielonych limitów. Ich stabilne pokrycie wymaga kontrolowanego zegara backendu i resetowalnego limitera.

Raporty pokrycia zostały przeliczone. Suite wzrósł z 142 do 170 testów, pokrycie operacji z 42/55 do 48/55, a wszystkie sześć operacji 2FA ma teraz dedykowany spec w projekcie klienckim.

Wynik testów

WalidacjaWynik
Proof of concept curl na awesome.byst.repełny cykl zakończony sukcesem, konto usunięte
Focused run npm test -- --project=api tests/api/users/2fa28/28 testów, 1,4 min
Pełny run npm test170/170 testów, 3,2 min
npm ls otplib --depth=0otplib@13.5.0
bash -n scripts/explore-2fa-poc.shbez błędów
git diff --checkbez błędów
Skan odwołań do stagingu w nowej warstwie 2FAbrak odwołań

Pełny run został wykonany po finalnych zmianach w kodzie testów, w tym po wyłączeniu trace i zaostrzeniu asercji rotacji kodów odzyskiwania.

Finalny efekt sesji

Checkpoint l18 ma teraz działające pokrycie całego klientowego cyklu 2FA na autorytatywnym środowisku kursowym. Testy sprawdzają zarówno TOTP, jak i kody odzyskiwania, chronią przed replayem, weryfikują zmiany stanu i sprzątają własne dane.

Poza kodem testowym pozostają cztery trwałe artefakty diagnostyczne: bezpieczny skrypt proof of concept, techniczny api-test-plan.md, stakeholderowy raport HTML oraz raport defektu OpenAPI. Najbliższym technicznym rozszerzeniem 2FA powinny być kontrolowany zegar i reset limitera, które umożliwią stabilne dodanie ścieżek 410 i 429 bez czekania 15 minut i bez zatruwania współdzielonego środowiska.