Mi aplicación consta de una API de back-end nodejs pero también estoy desarrollando una implementación de "referencia" de un cliente JavaScript, que es un backbone SPA .
En primer lugar; La API solo acepta solicitudes HTTPS, en caso de que una solicitud HTTP llegue al servidor, la ignora por completo y también (dependiendo de la configuración del cliente) invalida la contraseña proporcionada en esa solicitud insegura.
Mi servidor no tiene estado y solo uso autenticación básica HTTP (S) . Proporciono dos formas de autenticar una solicitud:
1- Enviando credenciales en el encabezado Authentication: base64('Basic ' + user:password)
2- Enviar una solicitud autenticada utilizando el método 1 a GET /users/current
que devuelve un token que es una cadena cifrada * que contiene: username + '|' + timeOfTokenExpiration
. El cliente luego envía solo el encabezado Authentication: base64('Token ' + username:returnedToken)
a partir de entonces.
* El cifrado se realiza con el algoritmo aes-256-ctr de OpenSSL, y la clave es el hash de contraseña del usuario
El método 1 se puede usar para una comunicación directa de servidor a servidor, pero no es adecuado para un cliente de JavaScript, ya que el usuario tendría que insertar sus credenciales en cada solicitud, lo que no es factible .
El almacenamiento de las credenciales de usuario en el almacenamiento local del navegador solucionaría este problema pero mantendría al usuario registrado indefinidamente, creando otra posible amenaza para la seguridad. Tampoco estoy seguro de lo seguro que es almacenar las credenciales en texto sin cifrar en la memoria del navegador .
Al utilizar método 2 , el cliente JavaScript enviaría solo una solicitud autenticada y luego almacenaría las credenciales cifradas en el almacenamiento local, después de un período de tiempo determinado tiene que volver a validar las credenciales del usuario, ya que eventualmente caducará y El servidor ya no aceptará solicitudes de ese token.
En el lado del servidor, compruebo la autenticidad de una solicitud del método 2 recuperando el hash de la contraseña del usuario y tratando de descifrarlo. Después del descifrado, compruebo si decryptedString.split('|')[0] === username
.
¿Es este un enfoque seguro / bueno?