[ Înapoi la blog

Rotația jetoanelor de reîmprospătare JWT: model sigur pentru sisteme reale

[Securitatea dezvoltatorului28 martie 2026·9 minute de citire]] [JWT refresh token rotation diagram

Majoritatea tutorialelor JWT se opresc la „utilizați un simbol de reîmprospătare pentru sesiuni de lungă durată”. Ei explică rareori ce se întâmplă când acel token de reîmprospătare este furat. Un simbol de reîmprospătare static – unul care nu se schimbă niciodată – oferă unui atacator același acces persistent ca un cookie de sesiune furat. Mai rău, nu există nicio modalitate de a detecta furtul.

Refresh token rotation solves this by issuing a new refresh token with every use. Dacă un jeton vechi este rejucat, întreaga sesiune este revocată. Acest articol prezintă modelul de implementare utilizat de Auth0, Okta și alți furnizori serioși de identitate.

De ce eșuează jetoanele de reîmprospătare statice

Un indicativ de reîmprospătare static are o valoare fixă pentru întreaga durată de viață a sesiunii (de multe ori peste 30 de zile). Probleme:

[
  • Furtul este silențios — dacă un atacator fură jetonul de reîmprospătare, poate genera noi token-uri de acces pe termen nelimitat fără ca utilizatorul să știe
  • Fără detectare a reluării — același simbol poate fi folosit în mod repetat din locații diferite
  • Revocarea este grosieră — pentru a invalida un simbol furat, adesea trebuie să invalidați toate sesiunile de utilizator
  • [

    Remedierea este de a trata fiecare jeton de reîmprospătare ca de unică folosință.

    [ de rotație

    Pasul 1: Conectați-vă — Creați o familie de jetoane

    Când utilizatorul se autentifică, generați un family_id (UUID) care grupează toate jetoanele din această sesiune:

    [{ family_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479", user_id: "user_123", refresh_token_hash: sha256(refresh_token), created_at: "2026-03-28T10:00:00Z", expires_at: "2026-04-27T10:00:00Z", used: false } [ această înregistrare pe partea de server. Nu stocați niciodată jetoane de reîmprospătare în Stocare locală — utilizați Numai http cookie-uri sau stocare nativă securizată.

    Pasul 2: Reîmprospătarea simbolului — Rotiți

    [ clientul prezintă indicativul de reîmprospătare:

    [ [ hash-ul simbolului în baza de date
  • Verificați că aparține unei familii active și nu este marcat ca utilizat
  • Marcați-l ca utilizat: true
  • Emiteți un nou jeton de reîmprospătare (nouă valoare aleatorie, același family_id)
  • [ un nou token de acces
  • Stochează noul hash token de reîmprospătare
  • [ [ 3: Detectarea reluării

    Dacă un jeton de reîmprospătare marcat ca utilizat: true este prezentat din nou, aceasta înseamnă fie:

    [
  • Un atacator redă din nou un jeton furat sau
  • [ client legitim reîncearcă după o eroare în rețea [

    Răspunsul sigur: [ toate jetoanele din familie. Acest lucru obligă utilizatorul să se conecteze din nou. Este mai bine să deranjezi un utilizator legitim o dată decât să lași un atacator să mențină accesul.

    // Reluare detectată — opțiune nucleară
    așteaptă db.query( „ȘTERGERE FROM refresh_tokens WHERE family_id = $1”, [familyId]
    );[
    [ bazei de date [ tabel minim de jetoane de reîmprospătare:

    [CREATE TABLE refresh_tokens ( id UUID CHEIE PRIMARIA DEFAULT gen_random_uuid(), family_id UUID NOT NULL, user_id UUID NOT NULL REFERENCES utilizatori(id), token_hash TEXT NOT NULL UNIQUE, folosit BOOLEAN DEFAULT FALSE, creat_la TIMESTAMPTZ DEFAULT acum(), expires_at TIMESTAMPTZ NOT NULL, înlocuit_de REFERINȚE UUID refresh_tokens(id) ); CREATE INDEX idx_refresh_family ON refresh_tokens(family_id); CREAȚI INDEX idx_refresh_user PE refresh_tokens(user_id);

    Coloana înlocuită_de creează un lanț pe care îl puteți urmări în scopuri de audit.

    [ solicitărilor concurente

    În aplicațiile reale, mai multe apeluri API pot declanșa o reîmprospătare simultan. Dacă Apelul A rotește jetonul în timp ce Apelul B îl mai deține pe cel vechi, Apelul B declanșează detectarea reluării — deconectarea utilizatorului în mod neașteptat.

    [ perioadei de grație

    Permiteți indicativului de reîmprospătare anterior să rămână valabil pentru o fereastră scurtă (5-10 secunde) după rotație:

    [const GRACE_PERIOD_MS = 10_000; if (token.used) { const elapsed = Date.now() - token.rotated_at; dacă (a trecut < GRACE_PERIOD_MS) { // Within grace period — return the already-issued new tokens return getLatestTokensForFamily(token.family_id); } // Outside grace period — replay attack await revokeFamily(token.family_id); throw new UnauthorizedError('token_replayed'); } [ și alerte [ aceste semnale în producție:

    [
  • Evenimente de reluare pe oră — un vârf indică un atac activ sau o eroare la nivelul clientului
  • Revocări ale familiei — ratele ridicate pot indica furtul de simboluri sau un client configurat greșit
  • Rata de reîmprospătare per utilizator — rate anormal de mari sugerează recoltarea de simboluri
  • Anomalii geografice — reîmprospătare dintr-o altă țară decât datele de conectare inițiale
  • [

    Jeton de reîmprospătare vs jeton de acces: Referință rapidă

    [ ProprietateJeton de accesJeton de reîmprospătare [Durata de viață5–15 minute7–30 de zile[[FormatJWT (autonom)Șir opac (recomandat) [StocareMemorie (variabilă JS)httpNumai cookie [Trimis la serverele APINumai serverul de autentificare RotireNu este necesarFiecare utilizare [

    Pentru erorile de validare a revendicării de timp care interacționează adesea cu fluxurile de reîmprospătare, consultați Erorile comune JWT exp/iat/nbf.

    [ [ frecvente

    Cum ar trebui să gestionez solicitările de reîmprospătare simultane?

    Utilizați o perioadă de grație scurtă (5–10 secunde) în care simbolul de reîmprospătare anterior este încă acceptat. Aceasta se ocupă de condițiile de cursă atunci când mai multe apeluri API declanșează o reîmprospătare simultan. După perioada de grație, doar cel mai nou simbol este valabil.

    Tokenurile de reîmprospătare ar trebui să fie JWT sau șiruri opace?

    Șirurile opace sunt în general mai sigure pentru jetoanele de reîmprospătare. JWT-urile transportă date de încărcare utilă care măresc suprafața de atac, iar jetoanele de reîmprospătare nu trebuie să fie autonome, deoarece oricum serverul le caută întotdeauna în baza de date.

    Cât timp ar trebui să reîmprospăteze sesiunile live?

    [ de zile sunt tipice. Aplicațiile de înaltă securitate (bancare, asistență medicală) ar trebui să utilizeze 1–7 zile. Aplicațiile pentru consumatori pot dura până la 90 de zile cu rotație. Asociați întotdeauna sesiunile lungi cu amprentarea dispozitivului și detectarea anomaliilor.

    [ [ și articole înrudite [
  • Decodor JWT — inspectează jetoanele și verifică revendicările de timp
  • Greșeli de securitate JWT — capcane comune JWT dincolo de jetoanele de reîmprospătare
  • Erori JWT Time-Claim — probleme legate de distorsiunea ceasului și ordinea de validare
  • Ghid 2FA — consolidați autentificarea dincolo de jetoane
  • [