TrendVidStream ha spostato l'intero stack di autenticazione su un sistema di rotating-refresh-token che individua un token rubato nel momento stesso in cui viene riutilizzato. Il cambiamento ha trasformato un JWT di 30 giorni, che un tempo permetteva a un attaccante di muoversi liberamente, in una credenziale a breve durata che attiva istantaneamente un blocco dell'account.
Una singola violazione ha imposto il passaggio: un SDK di un partner ha memorizzato in cache un JWT di 30 giorni in chiaro; un attaccante lo ha estratto e lo ha riutilizzato da un altro paese, e l'unico rimedio è stato ruotare la chiave di firma — un'operazione che ha disconnesso ogni utente. L'incidente ha ridefinito la sicurezza dei token dell'azienda e ora alimenta il servizio di video streaming.
Perché il vecchio modello è fallito
I JWT (JSON Web Tokens) sono blob firmati e autosufficienti che consentono a un server di verificare una richiesta senza consultare il database. Questa comodità nasconde un costo: se un token dura settimane, rubarlo garantisce all'avversario settimane di accesso. Durante la violazione, il token rubato è rimasto valido fino alla sua scadenza di 30 giorni perché non c'era modo di invalidarlo anticipatamente.
Ruotare la chiave di firma è l'unico modo globale per invalidare tutti i token, ma costringe ogni utente a effettuare nuovamente l'accesso, interrompendo il servizio e minando la fiducia. Il difetto non risiedeva nel JWT stesso, ma nel fare affidamento su un'unica credenziale a lunga durata.
Il nuovo design in sintesi
TrendVidStream ora emette due tipi di token:
- Access token – validi per 15 minuti; contengono i permessi necessari per ogni chiamata API.
- Refresh token – token monouso che scambiano un access token a breve durata con una nuova coppia.
Quando un client presenta un refresh token, il server:
- Verifica la firma e i claim del token.
- Controlla se il token è già stato utilizzato.
- Se il controllo passa, emette un nuovo refresh token e un nuovo access token di 15 minuti.
- Segna il vecchio refresh token come utilizzato.
Se il passaggio 2 fallisce — ovvero se lo stesso token appare una seconda volta — il server lo tratta come un segnale di furto e revoca l'intera "famiglia" di token collegati a quella sessione di login. Sia la vittima che l'attaccante sono costretti a effettuare nuovamente l'accesso, interrompendo tempestivamente la violazione.
Tracciamento delle famiglie di token
Invece di trattare ogni token come un record isolato, il sistema li raggruppa in famiglie che iniziano quando un utente effettua l'accesso. Ogni rotazione crea un nuovo membro di quella famiglia. Lo schema SQLite utilizzato in produzione memorizza:
- family_id – un identificatore stabile per l'intera sessione.
- token_id – un identificatore univoco per ogni refresh token.
- generation – un contatore utile per il debugging.
- used_at – timestamp di quando il token è stato riscattato.
- revoked – un flag che, se impostato, disabilita l'intera famiglia.
Quando viene rilevato un evento di riutilizzo, il flag revoked per quel family_id viene impostato, invalidando istantaneamente ogni token appartenente alla sessione compromessa. Questo trasforma un dirottamento silenzioso in un alert ad alto segnale che appare nei log.
Tre regole di implementazione per mantenere il sistema affidabile
Valida prima la firma Un attaccante potrebbe indovinare gli ID dei token e innescare revoche di massa se il server controlla "già usato?" prima di verificare la firma. Confermare prima l'autenticità previene attacchi di denial-of-service non necessari.
Consenti una finestra di tolleranza (grace window) Le app mobile spesso inviano due richieste di refresh in rapida successione quando un token scade. Se il server è troppo rigido, la seconda richiesta verrebbe segnalata come riutilizzo, disconnettendo un utente legittimo. Un buffer di pochi secondi permette a un token "già usato" di restituire comunque una nuova coppia, mitigando le race condition.
Avvolgi l'intero flusso in una transazione con blocco delle righe (row locking) Senza atomicità, due richieste concorrenti potrebbero pensare entrambe di essere le prime a utilizzare un token, emettendo refresh token duplicati e violando la garanzia di monouso. Una transazione del database che blocca la riga del token garantisce che solo una richiesta abbia successo.
In sintesi: Rendendo i refresh token monouso e monitorando il loro riutilizzo, un sistema può trasformare ogni credenziale rubata in un allarme, proteggendo gli utenti senza forzare una disconnessione di massa su tutta la piattaforma.
