Non descrivi molto bene questo passaggio:
If user login credentials are confirmed, a symmetrical AES-128 key is generated from their unencrypted password and their unique salt and attached to their session to decrypt the credentials of the third party accounts stored in the database.
Esattamente come viene creata la chiave a 128 bit? Questo dovrebbe essere un processo molto lento, altrimenti fornirai un canale laterale per le password utente a forza bruta. Il modo in cui funzionerebbe è che un hacker metta le mani sul tuo database. Piuttosto che provare a forzare la forza bruta degli hash di bcrypt, che richiederebbero molto tempo, si arriva a lavorare sulle password crittografate. Semplicemente forza-forza la password dell'utente per ottenere chiavi che sembrano funzionare (ad esempio: il testo decodificato sembra una password, qualunque cosa significhi). Questo sarà un attacco rapido perché la crittografia è veloce.
È necessario rendere la creazione della chiave a 128 bit un processo lento. Il modo migliore per farlo è probabilmente usare bcrypt. Ma, come probabilmente avete capito, non si vuole usare il valore bcrypt che hai memorizzato nel DB per l'autenticazione in quanto non sarebbe un modo sicuro per archiviare le chiavi di crittografia. Ti suggerisco di tenere un secondo sale per ogni utente. Quindi usi quel salt, oltre alla loro password in chiaro, in una chiamata a bcrypt per generare la chiave di crittografia a 128 bit.
Quando un utente cambia password, è necessario cancellare o ricodificare tutte le password crittografate. Ciò è necessario perché gli utenti cambiano frequentemente le password quando sono preoccupati che la loro password sia stata compromessa. Quindi è meglio cancellare i dati che sono stati crittografati con la password compromessa. Questo, ovviamente, non aiuterà se l'autore dell'attacco ha già ricevuto una copia del database prima che la password cambi.
Un'altra misura di sicurezza che potresti aggiungere è il pepe (cerca "pepe" nella questa risposta ) la crittografia chiave. Il pepe dovrebbe essere una stringa di bit veramente casuale (no, il nome del tuo gatto non si qualifica) che hai memorizzato qualche altro . Cioè, non è nel database. L'utilizzo di un peperone impedirà a un utente malintenzionato di ottenere sia una copia del database che una password dell'utente, decrittografando i dati dell'utente, poiché avranno ancora bisogno del pepe. Ricorda che un peperone è tanto utile quanto sicuro. Inserirlo nel repository di origine è probabilmente una cattiva idea.