Estoy creando una aplicación web donde el front-end es una aplicación de una sola página y el back-end la sirve a través de una API RESTful. Quiero asegurarme de implementar la autenticación de usuarios con las mejores prácticas de seguridad.
Estoy planeando un sistema que llevará a cabo los siguientes pasos para garantizar la seguridad de la autenticación:
Registrarse (o cambiar la contraseña):
- El usuario envía el nombre de usuario y la contraseña al servidor en texto sin formato a través de HTTPS
- La sal única se genera con la función
urandom
de Python (32 caracteres) - Sal ante la contraseña
- La contraseña de Salt + está oculta con
bcrypt
- Sal y hash almacenados en la tabla de la base de datos (base de datos SQL, más lenta que el valor clave, pero no me preocupa demasiado la velocidad excesiva para iniciar sesión)
- ID de sesión aleatoria generada con
urandom
(32 caracteres) - ID de sesión almacenada en db clave-valor (¿Redis? Clave: id de sesión, valor: id de usuario) y se envía al cliente junto con el objeto de usuario (obviamente sin sal y hash)
Iniciar sesión:
- Al iniciar sesión, el usuario envía el nombre de usuario y la contraseña al servidor en texto sin formato a través de HTTPS
- El servidor recupera sal y hash de la entrada de los usuarios en la base de datos SQL
- Salt antepuesto a la contraseña y a través de
bcrypt
- Si ambos hashes coinciden, la ID de sesión generada con
urandom
e ingresada en el db de clave-valor - ID de sesión enviada al cliente con objeto de usuario
Cualquier otra solicitud al servidor:
- Solicitud y datos enviados a través de HTTPS, incluidos el ID de usuario y el ID de sesión
- db valor-clave buscado con id de usuario, si coinciden los ids de sesión, devuelve los datos solicitados junto con el objeto de usuario
- Si no coincide, devuelve el error 401
Manejo de sesiones:
- Permitir más de una sesión para el mismo usuario
- Establezca la caducidad de la sesión en 24 horas; cuando acceda, vuelva a ponerla en 24 horas
- Permitir la sesión persistente que caduca en 1 mes, cuando se accede también se vuelve a poner al tiempo de caducidad completo
- Al cerrar sesión, eliminar sesión de Redis
¿Será este un sistema seguro, escalable y rápido (cuando sea necesario)? Si no, ¿dónde están las fallas de seguridad? ¿Qué podría hacer para mejorar este proceso? ¿Es esto vulnerable a los ataques CSRF? ¿Mejora la seguridad al agregar la dirección IP del cliente y USER_AGENT a la sesión o esto es una exageración?