¿Es este un enfoque lo suficientemente bueno para asegurar una API RESTful?

2

Quiero usar la autenticación basada en token donde el usuario inicie sesión con una combinación de nombre de usuario y contraseña. El servidor se aseguraría de que el nombre de usuario y la contraseña coincidieran y luego devolvería un token que el cliente usaría para realizar las siguientes llamadas a la API. Este token caducaría después de un cierto tiempo (4 horas es lo que estoy pensando), después de lo cual el usuario tendría que iniciar sesión nuevamente.

La forma en que quiero generar tokens es esta: SHA256 hashes de 3 cadenas generadas aleatoriamente (caracteres - [0-9, a-z, A-Z]), concatenadas. Almacenaría este token en una tabla de base de datos junto con el nombre de usuario y el tiempo de inicio de sesión.

Cuando se realice una solicitud de API con este token, podré obtener el usuario del token.

Quiero protegerme contra los ataques de fuerza bruta.

Quiero implementar todo esto en PHP. ¿Es este enfoque lo suficientemente bueno? Si no, ¿por qué? ¿Y cuál sería una mejor manera de hacerlo? ¿Debería haber una manera de obtener al usuario solo desde el token (sin buscar en una base de datos)? Si es así, ¿por qué?

Soy un novato en lo que respecta a la seguridad, por lo que las explicaciones detalladas serían muy apreciadas.

    
pregunta Ayush 02.09.2016 - 17:46
fuente

2 respuestas

2
  

La forma en que quiero generar tokens es esta: SHA256 hashes de 3 cadenas generadas aleatoriamente (caracteres - [0-9, a-z, A-Z]), concatenadas.

No hay ningún punto en el hashing de datos aleatorios .

Evite el uso de las funciones predeterminadas rand om, ya que son inseguras. Utilice un PSRNG criptográficamente seguro para generar los datos aleatorios. Por ejemplo, en sistemas similares a UNIX puede leer los datos de /dev/urandom . Espero que PHP tenga una forma documentada independiente de la plataforma para crear datos aleatorios criptográficamente seguros.

El token debe tener 72 bits de entropía o más .

  

Almacenaría este token en una tabla de base de datos junto con el nombre de usuario y el tiempo de inicio de sesión.

Como debe saber, no debe nunca almacenar contraseñas , sino usar un Hash lento como bcrypt.

Del mismo modo, para los tokens de sesión , tampoco debe almacenarlos, sino usar un Fast Hash para estos. Por lo tanto, su base de datos debe almacenar un hash SHA-256 del token. Evitar el almacenamiento del token original es útil para ciertos esquemas de administración de claves o ataques de casos de borde (es decir, SQLi limitado) que puede tener en el futuro.

  

Cuando se realice una solicitud de API con este token, podré obtener el usuario del token.

Suena bien.

  

Quiero implementar todo esto en PHP.

Estos conceptos son agnósticos del lenguaje. :-)

Debe asegurarse absolutamente de estar usando HTTPS / TLS para cifrar la conexión y verificar la identidad del servidor antes de enviar cualquier información de autenticación confidencial, como contraseñas o tokens de sesión.

Le recomendaría que también verifique que la dirección IP coincida con lo que era cuando el usuario inició sesión por primera vez. Si la dirección IP cambia durante la sesión, puede ser una pista de que el token fue robado .

Desafortunadamente, los usuarios de teléfonos móviles y los usuarios de ciertos países extranjeros cambian de dirección IP con frecuencia, por lo que esta restricción no funcionaría para ellos.

    
respondido por el George Bailey 02.09.2016 - 19:17
fuente
0

El enfoque "estándar" para esto (en mi opinión, haberlo hecho recientemente) es utilizar el flujo de propietarios de recursos de OAuth.

Esto significa que haces exactamente lo que sugieres, y creas un "access_token" que es de tipo vivido; luego, opcionalmente, un "refresh_token" que tiene una vida más larga y te otorga la posibilidad de obtener un nuevo access_token sin volver a ingresar tu credenciales.

El access_token puede, o no, estar almacenado en el almacén de datos de su aplicación para propósitos de revocación, sin embargo, no es un "indicador" de algo en la base de datos. Contendría toda la información que necesita para la solicitud. Así que esos son los identificadores de usuario, roles, orígenes, etc.

El access_token generalmente se envía como un encabezado de autorización, que es analizado por algún tipo de middleware y presentado a su código como datos sin procesar.

No estoy seguro de las tecnologías dentro de PHP para eso, pero los términos que debe buscar son: OAuth 2.0 y tokens de portador.

Mi último consejo es, no lo hagas tú mismo, hay personas que pasan su vida haciendo esto. Es más probable que te sientas inseguro al intentar hacerlo por tu cuenta.

    
respondido por el Martin 02.09.2016 - 19:00
fuente

Lea otras preguntas en las etiquetas