Sto implementando un sistema di autenticazione basato su token per un'API REST che utilizza un token di accesso di breve durata e un token di aggiornamento di lunga durata. Questa è una panoramica astratta degli endpoint API pertinenti (HTTPS viene applicato per tutti gli endpoint):
Endpoint:
POST /register/
POST /login/
POST /logout/
POST /password/change/
Implementazione:
POST /register/
:
- Richiesta: il client invia nome utente, email e password in JSON.
- Azioni server:
- Convalida l'input, crea l'utente nel database (memorizza l'id utente, il nome utente, l'e-mail e l'hash della password).
- Crea token di accesso di breve durata in formato JWT (contiene ID utente, data di emissione e data di scadenza).
- Crea token di aggiornamento a vita lunga come stringa UUID e lo memorizza nel database (memorizza l'ID utente e il token di aggiornamento).
- Risposta: il server restituisce il token di accesso e aggiorna il token in JSON.
POST /login/
:
- Richiesta: il client invia nome utente e password in JSON.
- Azioni server:
- Convalida l'input, controlla se le credenziali sono valide controllando il database.
- Se le credenziali sono valide, crea token di accesso di breve durata e token di aggiornamento a vita lunga come menzionato in precedenza.
- Risposta: come
/register/
, restituisce il token di accesso e aggiorna il token in JSON.
POST /logout/
:
- Richiesta: il client invia il token Aggiorna nell'intestazione
Authorization
come tokenBearer
. - Azioni server:
- Convalida il token di aggiornamento controllando il database dei token di aggiornamento.
- Rimuove il token di aggiornamento dal database.
Nota: questo lascia il token di accesso valido, ma dal momento che sarà di breve durata (1 ora o giù di lì, penso che dovrebbe andare bene ).
- Risposta: restituisce se la richiesta di disconnessione è stata elaborata correttamente in JSON.
POST /password/change/
:
- Richiesta: il client invia il token accesso nell'intestazione
Authorization
come tokenBearer
e invia anche la vecchia password e la nuova password in JSON tramite HTTPS. - Azioni server:
- Decodifica il token di accesso per recuperare l'utente e controlla la vecchia password dell'utente con il database.
- Imposta l'hash della password dell'utente nel database sull'hash della nuova password.
- Rimuove tutti i token di aggiornamento associati con l'utente nel database dei token di aggiornamento per disconnettere essenzialmente le sessioni esistenti (lasciano validi token di accesso di breve durata validi).
- Risposta: restituisce se la richiesta di modifica della password è stata elaborata correttamente in JSON.
Domande:
- Questo approccio è sicuro? In particolare:
- L'invio del nome utente e della password tramite JSON safe avviene su HTTPS? Come impedire ai domini non autorizzati di effettuare chiamate a questo endpoint? Inoltre, come impedirei gli accessi programmatici?
- I token di aggiornamento devono essere sottoposti a hash prima di archiviarli nel database o sono solo paranoico?
-
Se il client fosse un browser web, come conserverei in modo sicuro il token di aggiornamento sul client?
- Un'idea che ho per memorizzare il token di aggiornamento è: quando l'utente esegue l'accesso, oltre a inviare il token di aggiornamento al client, il server memorizza il token in un cookie
HttpOnly
con un flagsecure
. L'autorizzazione verrà comunque eseguita tramite l'intestazioneAuthorization
, ma quando il client si carica inizialmente, può inviare una richiesta diGET
a un endpoint che verifica se il cookie contiene un token di aggiornamento valido e, in caso affermativo, restituirlo al utente in JSON. In altre parole, l'unica volta in cui il cookie verrà effettivamente utilizzato è quello di restituire il token di aggiornamento all'interno del cookie al client. Questo approccio è sicuro? Penso che impedirà CSRF perché non ci sono effetti collaterali quando si richiede il token di aggiornamento dal cookie, ma esiste un altro modo in cui un utente malintenzionato potrebbe intercettare il token di aggiornamento (supponendo HTTPS)?
- Un'idea che ho per memorizzare il token di aggiornamento è: quando l'utente esegue l'accesso, oltre a inviare il token di aggiornamento al client, il server memorizza il token in un cookie