Come implementare la funzionalità "password dimenticata"?

65

Per il mio progetto ho bisogno di una funzionalità " cambia password ".

Non sono ancora sicuro di come implementare questo tipo di funzionalità, quindi speravo di trovare alcune "best practice" su Internet, ma non ho trovato nulla di utile che tratta ogni aspetto importante di questa caratteristica abbastanza comune.

I miei pensieri su questo sono piuttosto semplici:

Se un utente volesse cambiare la sua password, potrei creare un token univoco uniqueTokenForTheUser collegato a una "richiesta di modifica della password" che sarebbe essenzialmente l'identificativo del mio backend per capire se era l'utente giusto a inviare la richiesta.

Quindi, ad esempio, vorrei generare / inviare un messaggio di posta elettronica a [email protected] con un link

http://www.example.com/changePassword?token=uniqueTokenForTheUser

uniqueTokenForTheUser verrebbe memorizzato in una tabella che viene controllata da un thread in un determinato intervallo e rimuove il record una volta che il token è scaduto nel caso in cui l'utente non abbia effettivamente cambiato la sua password.

Sebbene questo mi sembri piuttosto semplice, volevo verificare due volte se esistessero "buone pratiche", ad es. quando si tratta di generare e cancellare quel particolare token.

Qualsiasi suggerimento o riferimento ad articoli / tutorial sono i benvenuti!

Link aggiuntivi suggeriti dai commenti:

posta displayname 18.03.2016 - 11:13
fonte

4 risposte

62

Utilizza HTTPS solo per questo, e poi entreremo nei dettagli dell'implementazione.

Prima di tutto vorrai proteggere contro enumerazione utente .

Cioè, non rivelare nella pagina se l'utente esiste o no. Questo dovrebbe essere divulgato solo nell'e-mail stessa.

In secondo luogo vorrai evitare perdita di referrer . Assicurati che non siano presenti collegamenti esterni o risorse esterne sul tuo link di destinazione. Un modo per attenuarlo consiste nel reindirizzare dopo aver seguito il collegamento iniziale in modo che il token non sia più nella stringa di query. Tieni presente che se qualcosa va storto (ad esempio il tuo database è brevemente inattivo) e viene visualizzato un modello di errore standard, questo potrebbe causare la perdita del token nel caso in cui contenga riferimenti esterni.

Genera un token con 128 bit di entropia con un CSPRNG. Archivia questo lato server utilizzando SHA-2 per evitare che eventuali vulnerabilità di perdita di dati sulla tabella di ripristino impediscano a un utente malintenzionato di reimpostare le password. Si noti che il sale non è necessario. Scade questi token dopo un breve periodo di tempo (ad esempio alcune ore).

Oltre a fornire il token non hash per l'utente nel collegamento e-mail, dare all'utente l'opzione di accedere manualmente alla pagina e quindi incollare il valore del token. Questo può impedire che i valori della stringa di query vengano registrati nella cronologia del browser e all'interno di qualsiasi registro proxy e server per impostazione predefinita.

Opzionalmente potresti voler assicurarti che l'identificatore di sessione per la sessione che ha avviato la reimpostazione della password sia quello che ha seguito il collegare . Ciò può aiutare a proteggere un account in cui l'utente malintenzionato ha accesso alla posta elettronica dell'utente (ad esempio, impostazione di una regola di inoltro rapido di tutte le regole con accesso limitato all'account di posta elettronica). Tuttavia, tutto ciò che realmente fa è impedire a un utente malintenzionato di seguire opportunisticamente un reset richiesto dall'utente - l'utente malintenzionato potrebbe comunque richiedere il proprio token di reimpostazione per la vittima nel caso in cui desideri indirizzare il proprio sito.

Una volta che la password è stata reimpostata su una delle scelte dell'utente, è necessario scadere il token e inviare all'utente una e-mail per far sapere che ciò è accaduto nel caso in cui un utente malintenzionato sia in qualche modo riuscito a reimpostare la propria password (senza necessariamente avendo il controllo del proprio account di posta) - difesa approfondita. Dovresti ruotare anche l'identificatore di sessione corrente e scadere gli altri per questo account utente . Ciò annulla la necessità che l'utente debba effettuare di nuovo il login, mentre cancella anche le sessioni guidate da un utente malintenzionato, sebbene alcuni utenti preferiscano che il sito effettui il log in modo che ottengano una comoda schermata di conferma che la password è stata effettivamente ripristinata. Il reindirizzamento alla pagina di accesso offre inoltre a alcuni gestori di password la possibilità di salvare l'URL di accesso e la nuova password, sebbene molti già rilevino la nuova password dalla pagina di reimpostazione.

Potresti anche prendere in considerazione altre opzioni fuori banda per il meccanismo di reset e le notifiche di modifica. Ad esempio, tramite SMS o avvisi sul cellulare.

    
risposta data 18.03.2016 - 13:14
fonte
10

La tua linea di pensiero è sulla strada giusta. Tuttavia, suggerirei di descrivere il flusso per la funzionalità della password dimenticata da un passaggio precedente. Qualcuno dichiara di aver dimenticato la password, è necessario assicurarsi di identificare che questa persona è effettivamente il proprietario dell'account per il quale si avvia la procedura di recupero della password.

Il flusso sottostante presuppone un servizio in cui le persone possono iscriversi, ad esempio un sito Web (in altre parole, è possibile creare un elenco di e-mail e / o nomi utente registrati utilizzando la funzionalità di registrazione).

passaggio uno: identifica l'utente

  1. Facendo clic sul link "Oops, ho dimenticato la password", presenti l'utente con un modulo in cui inseriscono il nome utente e l'indirizzo e-mail (facoltativamente fornisci loro un suggerimento all'indirizzo e-mail sotto forma di: 's ... .. @ o .... com ');
  2. informali se l'indirizzo e-mail che hanno inserito appartiene al nome utente che hanno inserito (sì o no);
  3. Se il nome utente e la password immessi corrispondono, continua con i passaggi successivi.

passaggio due: avvia la procedura di ripristino

  1. genera un token di ripristino casuale (128 bit dovrebbe andare bene);
  2. memorizza un hash di questo token (creato utilizzando un algoritmo di hashing della password), insieme al suo timestamp di creazione nel database;
  3. invia all'utente un'e-mail con un collegamento (contenente il token di ripristino) a un modulo per la modifica della password. L'URL per il modulo per la modifica della password deve essere HTTPS.
  4. quando ricevi la richiesta di modifica della password, controlli: [1]. la validità del token (utilizzando il suo tempo di creazione rispetto all'ora corrente, in genere una finestra temporale di 10 minuti dovrebbe essere sufficiente); [2]. se il token presentato è corretto (hash il token, confronta l'hash risultante con quello nel tuo database, proprio come faresti per una password);
  5. se passano tutti i controlli, continua con il passaggio successivo.

Passaggio tre: aggiorna la password

  1. distruggi tutte le informazioni "ricordami" che potresti aver memorizzato per questo utente;
  2. distrugge tutte le sessioni attive associate a questo utente;
  3. aggiorna la password dell'utente;
  4. facoltativamente invia un'email al loro indirizzo email per informarli della modifica;
  5. registra l'utente in.
risposta data 18.03.2016 - 12:14
fonte
6

Sei vicino alle migliori pratiche con il tuo approccio. Una piccola aggiunta sarebbe:

  • Potrebbe essere necessario che il nome utente corrisponda al token anziché dedurre l'utente dal token.

  • Devi usare https piuttosto che http.

Le altre domande:

  • Per quanto riguarda la generazione: un modo usuale di generare quelli sta usando gli UUID, ma come sottolineano i commenti, dovresti piuttosto usare una stringa sufficientemente casuale, sufficientemente lunga.

  • Per quanto riguarda la cancellazione: puoi ripulire regolarmente token vecchi e non utilizzati come suggerito. Forse usa un intervallo di tempo che permetta alla posta di superare il solito grayler via email, ad es. 15 minuti.

risposta data 18.03.2016 - 11:22
fonte
3

Alcune riflessioni su questo:

  • L'email è intrinsecamente insicura. Il token potrebbe essere rubato ovunque tra il tuo server e la posta in arrivo degli utenti da un utente malintenzionato. Prendi in considerazione l'utilizzo di un altro mezzo di comunicazione, se possibile, come SMS.
  • Se vai via email, il link di ripristino dovrebbe essere su HTTPS, non su HTTP. Almeno quella parte del processo può essere crittografata.
  • Per prevenire gli attacchi di enumerazione degli utenti, è probabile che tu voglia visualizzare lo stesso messaggio o meno il nome utente / indirizzo e-mail in cui l'utente entra o meno. (Almeno non commettere l'errore di visualizzare l'e-mail dopo che l'utente ha inserito solo il nome utente.)
  • Usa un buon generatore di numeri pseudo casuali e un token lungo. Nessuno dovrebbe essere in grado di indovinare il token. Per rendere più difficile l'identificazione dei token, è necessario che l'utente inserisca sia il nome utente che il token. Limitare il numero di tentativi (per username e / o IP) impedirà anche la forzatura bruta. Forse anche un CAPTCHA?
  • Si desidera limitare per quanto tempo un token è valido. L'email potrebbe essere lenta se rimane bloccata nei filtri, ma non vedo alcun motivo per cui qualcuno avrebbe bisogno di più di dire mezz'ora.
  • Una volta ripristinato un account, termina tutte le sessioni precedenti per quell'account. L'utente potrebbe voler ripristinare l'account perché è stato compromesso e quindi l'utente malintenzionato dovrebbe essere disconnesso.
  • Invia solo un token monouso e non una nuova password! Le password non devono mai essere inviate tramite email.
  • Consenti solo di utilizzare un token una sola volta! Eliminalo immediatamente dopo l'uso (anche se l'utente non cambia la password).

Per ulteriori letture sull'argomento, ti consiglio Troy Hunt .

    
risposta data 18.03.2016 - 13:05
fonte

Leggi altre domande sui tag