Mi sono interessato all'implementazione del metodo di autenticazione per un'app Web che viene eseguita nei browser moderni, senza dover inviare la password sul filo.
Qualcuno può suggerire miglioramenti o persino dirmi se sto sbagliando o meno.
L'autenticazione viene eseguita tramite una connessione HTTP non protetta utilizzando AJAX.
Le mie attuali conoscenze sull'implementazione di un protocollo di autenticazione
Il server ha una password utente che è stata sottoposta a hash con bcrypt e archiviata durante la registrazione.
L'utente inserisce id
e password
. Un XMLHttpRequest
viene inviato al server per iniziare l'autenticazione, X-R1
è un numero intero casuale creato sul client.
GET /auth/{id} HTTP/1.1
X-R1: 123412341234
-
Il server ottiene i valori.
-
ServerPassword
- gli utenti bycrpt hanno cancellato la password dal database delle password -
X-Salt
- estrae il sale daServerPassword
-
X-R1
- dal client nell'intestazione della richiesta -
X-R2
- numero intero generato casualmente sul server.
-
-
Il server crea valori
-
X-Session
- chiave di sessione, concatenandoX-R1 + X-R2 + id
allora un solo modo esegue l'hash di questa stringa -
Verifier
- segreto condiviso, concatenazione diX-R1 + X-R2 + ServerPassword
e quindi hashing unidirezionale di questa stringa. -
Salva questi valori in un archivio di sessioni.
-
Risposta del server.
HTTP/1.1 202 ACCEPTED
X-R2: 432143214321
X-Salt: $2a$10$rBV2JDeWW3.vKyeQcM8fFO
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
-
Il client ottiene valori
-
X-R1
- stesso valore di prima dell'invio della richiesta. -
ClientPassword
- testo semplice, quale utente ha inserito. -
X-R2
- dall'intestazione del server inviato -
X-Salt
- dall'intestazione inviata dal server.
-
-
Il cliente crea valori
-
HashedPassword
- creato utilizzando un'implementazione JavaScript di bcrypt utilizzandoClientPassword
eX-Salt
-
Verifier
- Concatenamento diX-R1 + X-R2 + HashedPassword
e quindi un modo di hashing di questo valore. Il client utilizza un'implementazione JavaScript di bcrypt per hash la password che l'utente ha immesso con la stringa diX-Salt
.
-
Ora il client e il server pensano entrambi di avere lo stesso verificatore per confermare che questo client invia un'ulteriore richiesta, ma questa volta esegue l'hashing delle intestazioni e del corpo della richiesta con il verificatore e quindi aggiunge "X-Auth" alle intestazioni con hash risultante.
POST /auth/{id} HTTP/1.1
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
X-Auth: ad801198a9fab4e4ef79eb97624a4bf9c78b450a
Il server ora ricerca X-Sessions
nel suo archivio di sessioni. Fa lo stesso hashing delle intestazioni e del corpo della richiesta e poi controlla se l'hash corrisponde al valore di X-Auth
, in tal caso il server presuppone che il client sia autorizzato e risponda di conseguenza.
HTTP/1.1 200 OK
Il client sa che il server ha lo stesso Verifier
e lo memorizza in localStorage
usando il valore di X-Session
per la chiave, per ulteriori richieste.
Preoccupazioni
Sono uno sviluppatore medio e nessun esperto di crittografia e dalla mia comprensione non riesco a vedere eventuali problemi che potrebbero verificarsi con questo metodo.
Riesco a vedere i grandi vantaggi, come ad esempio:
-
La password non viene mai inviata tramite cavo. Impedisci al MITM di ottenere la tua password.
-
MITM non può modificare la richiesta poiché è stata sottoposta a hashing con il verificatore e quindi inviata.
-
Il server non ha bisogno di usare bcrypt ogni volta che un utente vuole autenticarsi.