Sto lavorando su un'API per un servizio REST che sto per produrre e consumare. Ho passato gli ultimi giorni a cercare di capire come gestire bene l'autenticazione, e penso di aver finalmente trovato qualcosa.
Sto arrivando a questo in base ai seguenti fatti sullo stack di applicazioni:
- Client & I server sono in .NET4 (parte client nel profilo client)
- Il server espone usando WCF REST
- Veramente non voglio mantenere il nome utente e la password in memoria nell'app
Da 3, volevo utilizzare una forma di autenticazione token, in modo che dopo che le credenziali sono state verificate dal server, il client recupera un token da utilizzare nel resto dell'app (questo mi permetterà di fare altre cose , come il time-out degli utenti, essere in grado di spostare gli utenti senza problemi tra le versioni web e desktop, ecc.). Dopo aver scoperto come rendere le chiamate replay e resistenti alle manomissioni, ho trovato il seguente:
- Prima che il client tenti di autenticare, genera una coppia di chiavi Diffie-Hellman utilizzando la classe
ECDiffieHellmanCng
. - Invia la parte pubblica della coppia di chiavi sul filo insieme al nome utente e alla password (Over HTTPS ovviamente).
- Il server autentica la combinazione nome utente / password, se ha esito positivo, quindi effettua le seguenti operazioni:
- Crea un token di sessione univoco
- Genera la propria coppia di chiavi DH e calcola il segreto condiviso dalla chiave pubblica fornita dal client
- Prende nota del token di sessione, del segreto condiviso, dell'utente e dell'ora "ultima azione" (utilizzata per una finestra di scadenza a rotazione) nel suo database
- Restituisce il token di sessione, la sua chiave DH pubblica e un messaggio di successo dell'autenticazione
- Il cliente prende la chiave DH dalla risposta, calcola il segreto condiviso e memorizza entrambi i token e i segreti nella memoria.
Da questo momento in poi, la combinazione di token / segreto di sessione funziona come la maggior parte delle altre API REST, con la richiesta di impronte digitali e timestamp, e quindi di generare una sorta di HMAC generato. Ogni volta che un client esegue un'azione contro il server, controlla la coppia token / secret e autorizza l'azione se è valida e non è scaduta e aggiorna l'ultimo record di azione nella sessione.
Non vedo difetti evidenti, ed è probabilmente troppo ingegnerizzato per questo, ma ho bisogno di imparare come farlo a un certo punto. L'HMAC previene gli attacchi di replay, la negoziazione del DH aiuta a prevenire gli attacchi del MITM (non riesco a pensare ad un attacco praticabile dalla parte superiore della mia testa tra HMAC / DH).
Qualche buco in cui qualcuno può colpire?