Bug-ul
O aplicație web B2B își loghează utilizatorii cu linkuri de unică folosință trimise pe e-mail. Căsuțele de e-mail ale firmelor trec adesea printr-un scanner de securitate care deschide linkurile dintr-un mesaj primit ca să le verifice înaintea omului. Scanarea e o vizită reală. Consumă token-ul de unică folosință, așa că, până dă utilizatorul click, linkul e deja folosit.
Cum se vede
Toți testerii de pe Gmail se loghează fără probleme. Apoi se înscriu primele firme, iar utilizatorii lor dau click pe link și primesc „Email link is invalid or has expired”. Cer un link nou, și acela ajunge tot folosit. Sunt afectați doar clienții business care au un scanner pe e-mail, adică de obicei cei care plătesc, iar ei dau vina pe produs.
Cum îl găsește un test
Faci ce face scannerul. Ceri linkul de login o dată cu un client HTTP simplu, cum îl descarcă un scanner de securitate, apoi deschizi același link în browser, ca utilizatorul. Dacă a doua vizită pică, orice client din spatele unui astfel de scanner rămâne pe dinafară. Testul se scrie în câteva minute și nu are nevoie de un cont Microsoft.
Reparația
Trimiți un cod de unică folosință pe care utilizatorul îl tastează, în locul linkului. Sau linkul deschide o pagină cu un buton „Confirmă autentificarea”, iar token-ul se consumă doar când un om apasă butonul. Scannerul încarcă pagina și lasă token-ul neatins.
Testul care îl prinde
Un test deschide linkul de login o dată cu un client HTTP simplu, cum ar face un scanner, apoi îl deschide în browser și verifică faptul că utilizatorul ajunge logat. Rulează în CI la fiecare schimbare în fluxul de login.
import { test, expect, request } from "@playwright/test";
import { requestLoginLink, signInFrom } from "./auth";
test("a mail scanner doesn't use up the login link", async ({ page }) => {
const link = await requestLoginLink("buyer@company.example");
// What an email security scanner does: fetch the link before anyone clicks.
const scanner = await request.newContext();
await scanner.get(link);
await signInFrom(page, link);
const expired = page.getByText("Email link is invalid or has expired");
await expect(expired).toHaveCount(0);
await expect(page.getByRole("button", { name: "Sign out" })).toBeVisible();
});
Ce pune în pericol
Conturile de firmă pentru care a fost construit produsul, chiar în momentul în care îl încearcă prima oară. O echipă care nu se poate loga din prima zi s-ar putea să nu mai încerce.
