Actualmente estoy en el proceso de construir un SPA SPA y he estado investigando cómo protegerlo. Actualmente hay una API REST con la que se está interactuando completamente a través de AJAX. También tenemos clientes móviles que interactúan con esta API, y actualmente solo es compatible con la autenticación básica HTTP a través de SSL. La aplicación JavaScript también se comunicará exclusivamente a través de SSL, pero BASIC Auth no la cortará, ya que eso implicaría almacenar la contraseña (o un derivado de ella) en el cliente. Por último, la aplicación SPA será JavaScript y HTML puros, servidos en el mismo servidor que la API RESTful, pero sin ningún marco del lado del servidor.
Objetivos :
- No hay un marco del lado del servidor para el cliente javascript (es solo otro cliente).
- Mantenga la apatridia de la API REST, por las razones típicas (escalabilidad, tolerancia a fallos, implementación simplificada, etc.)
- Cualquier estado debe ser mantenido por el cliente. Para los propósitos de esta pregunta, esto significa las credenciales de inicio de sesión.
- El estado de inicio de sesión mantenido por el cliente debe ser seguro y resistente al secuestro de sesión y ataques similares.
Lo que he encontrado se basa en mi investigación de OAuth y esquemas similares (Amazon, etc.).
- El usuario iniciará sesión con HTTP POST sobre SSL.
-
El servidor calculará un hash de la siguiente manera:
HMAC (key, userId + ":" + ipAddress + ":" + userAgent + ":" + todaysDateInMilliseconds)
-
Este token se devolverá al cliente y se suministrará con cada solicitud posterior en lugar del nombre de usuario y la contraseña. Lo más probable es que se almacene en localStorage o en una cookie.
¿Esto es seguro? Mi motivación para elegir userId, ipAddress, todaysDateInMilleseconds es crear un token que sea válido solo hoy, pero que no requiera una búsqueda en la base de datos para cada solicitud Y que sea seguro almacenarlo en el cliente. No puedo confiar en que la clave no se comprimirá, por lo tanto, la inclusión de la dirección IP en un intento de evitar el secuestro de la sesión.
Permítame incluir el siguiente enlace de una publicación relacionada en StackExchange porque creo que aborda muchos de los problemas que intento resolver: REST y los Id. de sesión sin estado
Después de la respuesta inicial aquí, he decidido usar solo los dos primeros octetos de la dirección IP para manejar mejor a los clientes que están detrás de proxies y móviles. Todavía no es perfecto, pero es una compensación por alguna seguridad adicional.