Această practică implică generarea unui șir unic, criptografic aleatoriu pentru fiecare cerere de resetare a parolei, care devine invalidă imediat ce este utilizată sau după o perioadă scurtă (de obicei 15-60 de minute). Este esențială deoarece previne atacurile de tip replay, unde un hacker interceptează sau furește un token valid și îl folosește ulterior pentru a prelua controlul contului. Dacă ignori acest aspect, chiar și un token expirat sau consumat ar putea rămâne activ, transformând o simplă funcționalitate de recuperare într-o vulnerabilitate critică de acces neautorizat.
Cum o aplici
- Generare sigură: Folosește un generator de numere aleatoare criptografic (CSPRNG) pentru a crea token-ul. Evită
Math.random()sau ID-urile incrementale. - Stocare sigură: Salvează hash-ul token-ului în baza de date, nu textul simplu. Asociază-l cu ID-ul utilizatorului, data expirării și un flag
used. - Expirare strictă: Setează un TTL (Time-To-Live) scurt în baza de date sau folosește coloane cu tip
DATETIMEpentru verificare la fiecare cerere. - Invalidare imediată: Marcare token ca
used=trueîn aceeași tranzacție atomică cu generarea parolei noi.
Exemplu
Varianta incorectă expune token-ul în URL și nu verifică expirarea:
// GREȘIT: Token vizibil și fără expirare reală
const resetLink = `/reset-password?token=${userId}&code=123456`;
Varianta corectă folosește hash și verifică timpul:
// CORECT: Hash și verificare timp
const crypto = require('crypto');
const token = crypto.randomBytes(32).toString('hex');
const hashedToken = crypto.createHash('sha256').update(token).digest('hex');
// În baza de date se stochează hashedToken + expires_at
// La cerere:
if (Date.now() > user.resetTokenExpiresAt || user.isResetTokenUsed) {
throw new Error("Token invalid sau expirat");
}
Cum verifici
- Teste de integrare: Scrie teste care încearcă să utilizeze același token de două ori consecutiv; al doilea apel trebuie să eșueze.
- Verificare temporală: Simulează trecerea timpului (sau modifică ceasul serverului) pentru a valida că token-urile vechi sunt respinse automat.
- Audit log: Verifică dacă sistemul generează evenimente de succes/eșec pentru fiecare cerere de reset, facilitând detectarea tentativelor brute-force.
Greșeli frecvente
- Stocarea token-ului în clar: Dacă baza de date este compromisă, atacatorul poate reseta orice parolă fără a ști parola curentă.
- Lipsa invalidării după utilizare: Un token care rămâne valid după schimbarea parolei permite accesul repetat la contul victimei.
- Timp de expirare prea lung: Perioade de 24 de ore sau mai mult cresc fereastra de oportunitate pentru interceptarea și reutilizarea token-urilor.
Resurse gratuite
Alte subiecte din „Autentificare”
- Folosește OAuth 2.1 și OpenID Connect, nu scheme de autentificare proprii
- Folosește fluxul Authorization Code cu PKCE pentru toți clienții
- Nu folosi fluxurile Implicit și Resource Owner Password Credentials
- Stochează parolele cu Argon2id sau bcrypt, niciodată în clar
- Oferă MFA și passkeys (WebAuthn) pentru conturile utilizatorilor
- Returnează mesaje generice la eșecul autentificării, fără enumerare de conturi
- Tratează cheile API ca secrete: scope limitat, rotație și revocare