¿Cómo diseñar la autenticación de usuario desde las aplicaciones cliente?

14

He estado desarrollando una aplicación que admitirá a muchos usuarios. El problema es que no puedo averiguar cómo autenticar al cliente / usuario.

Estoy creando una aplicación como enlace donde les daré credenciales a mis usuarios y las usarán para crear N aplicaciones en las que no pueden poner su nombre de usuario y contraseña para autenticarse.

Supongamos que sigue los siguientes pasos. (Al igual que QuickBlox)

1. El usuario crea una cuenta en mi sitio web.
2. El usuario puede crear claves N API y secretar credenciales. (Para múltiples aplicaciones)
3. El usuario usará estas credenciales en sus aplicaciones (Android, iOS, Javascript, etc.) para hablar con mis API REST.
(Las API REST tienen acceso de lectura y escritura).

¿Mi preocupación?

Los usuarios pondrán sus credenciales (clave de API y clave secreta) en las aplicaciones que construyen, ¿qué sucede si alguien obtiene estas claves e intenta imitar al usuario? (Descomprimiendo APK o buscando directamente en el código JavaScript.

¿Estoy equivocado en algún lugar?
Estoy confundido con el diseño de este mecanismo de usuario de tres niveles.

    
pregunta Alok Patel 02.08.2016 - 05:44

7 respuestas

6

He estado diseñando API REST durante los últimos años. Te estás preocupando demasiado. Recientemente, otro usuario en este foro ha formulado una pregunta, en la que estaba preocupado por almacenando puntos URI en su código del lado del cliente de JavaScript .

Las mismas reglas se aplican a usted como se aplica al desarrollador de JavaScript. Si permite que personas del exterior integren su API, su API tiene la misma visibilidad que un sitio web normal y debe tratarlo de la misma manera.

Cita de la respuesta original:

  

Cuando creas un sitio web y no quieres que los usuarios lo hagan   algo, no implementas esa funcionalidad ni prohibes ciertas   usuarios de usarlo. Con una API REST que debería tener público.   puntos finales es más o menos lo mismo, hay que tratarlo como un   sitio web público.

     

Su API REST debe ser lo suficientemente robusta como para no permitir operaciones no válidas,   como el acceso a datos de un usuario diferente.

Debe diseñar sus tokens de acceso a la aplicación para permitir solo las operaciones que desea permitir. Podría tener dos tipos de tokens de acceso:

  • token maestro : podría ser utilizado por el creador de la aplicación y proporcionar más funcionalidades desde su API,
  • token de aplicación : el token que realmente se almacenaría dentro de las aplicaciones y tendría un acceso limitado a su API, solo a las operaciones que no pueden corromper la suya o los datos del programador de la aplicación.

¿Pero lo que alguien deconstruye el código fuente, quita los tokens de la aplicación, descubre cuáles son los puntos finales públicos y abusa de su servicio web?

A menos que esté administrando directamente el desarrollo de las aplicaciones que consumen su API, nada realmente prohíbe que las personas abusen de su API de la misma manera directamente desde la aplicación.

    
respondido por el Andy 04.08.2016 - 08:16
5

Su problema no es tanto técnico como de negocios.

Supongamos que tiene su API, que vende a sus clientes (los desarrolladores de aplicaciones) por una tarifa fija de £ 100 al año, acceso ilimitado.

Obviamente, puedo comprar su servicio a £ 100 y venderlo a 10 personas a $ 50 cada uno. ¡No quieres eso! así que intenta pensar en una restricción que te permita vender tu API sin que esté abierta al arbitraje.

  • Si solo restringes el número de Aplicaciones, un cliente puede crear una única aplicación que acepte conexiones de otras aplicaciones y las transmita.

  • Si limita a los usuarios, nuevamente, el cliente puede ocultar a los usuarios detrás de su propia autenticación y parecer ser un solo usuario.

Lo que debe hacer es pasar el costo de cada llamada a la API a su cliente. es decir, cobrar por llamada API o establecer una cuota de llamadas por año.

Esto empuja el mismo problema de arbitraje a sus clientes. Los obliga a establecer medidas para evitar que sus usuarios roben sus claves. En este caso, ocultando su api detrás de su propio usuario autenticado api.

    
respondido por el Ewan 04.08.2016 - 10:32
2

Las otras respuestas parecen sugerir que el problema de almacenar un secreto en una aplicación en dispositivos de los consumidores no se puede resolver.

Claro que lo es.

Dos principios (los detalles de la implementación seguirán):

  1. Los puntos finales de autenticación reales deben estar abiertos de forma anónima al público.
  2. El servidor debe involucrarse de alguna manera en la autenticación del cliente y proporcionar una clave API.

Dado que, si el cliente realiza una solicitud al punto final de autenticación con credenciales, y el servidor lo autentica, el servidor puede generar un token dinámico temporal (significado temporal basado en el tiempo). Este token debe ser recordado dentro del cliente y enviado con solicitudes posteriores.

Necesitará un mecanismo para "actualizar" periódicamente el token, es decir, obtener uno nuevo. Simplemente cree un punto final REST que permita generar un nuevo token a partir de uno existente, para evitar tener que volver a autenticarse desde las credenciales.

Si está tratando de evitar que el usuario final se vuelva a autenticar, entonces esta autenticación puede ser una configuración inicial única en la aplicación cuando se instala.

Esta solución simplemente evita la necesidad de almacenar un token estático incrustado dentro del binario de la aplicación. El servidor genera un token sobre la marcha solo en respuesta a una autenticación exitosa. Para que un usuario malintencionado inspeccione su aplicación e intente obtener acceso a la API no autorizado, aún necesitarán autenticarse como cualquier otra persona.

    
respondido por el Brandon 08.08.2016 - 15:37
0

Si tiene claves únicas por aplicación, podría usarlas solo durante una autenticación de conexión inicial, iniciada por el cliente, y luego cambiará a un token de autenticación único por aplicación sucesiva.

Su servidor cambia (enrolla) el token para cada aplicación cliente de vez en cuando (por ejemplo, más / menos algún retraso aleatorio / difuso aleatorio, por ejemplo). El token rodante solo es conocido entre el servidor y el cliente autenticado.

Los nuevos tokens se devuelven guardados en las respuestas regulares. Siempre que la respuesta contenga un token nuevo, la aplicación receptora debe cambiar para usarlo en solicitudes posteriores.

Siempre que el intercambio con un cliente se desincronice (algún error de protocolo de algún tipo), su servidor solicitará una nueva autenticación (a través de una respuesta de error a la siguiente solicitud del cliente, o se incluirá en la respuesta válida al cliente solicitud, por ejemplo).

La autenticación inicial iniciada por los clientes mientras se usa activamente un token rodante debe considerarse con sospecha, podría muy bien ser un intento de imitación. Solo lo permitiría si el intercambio se queda inactivo durante un intervalo mayor al esperado, lo que, por ejemplo, podría ser causado por una interrupción / reinicio del cliente con una nueva instancia que no tiene el token rodante.

Sería incluso mejor persistir el token en el lado del cliente para que un cliente reiniciado pueda continuar desde donde se fue su predecesor, lo que reduce significativamente la apertura para la imitación.

Tal esquema haría que la imitación fuera al menos bastante difícil: el cliente de imitación tendría que predecir exactamente la ventana cuando el cliente autorizado deje de enviar solicitudes el tiempo suficiente para que el servidor decida que está bien aceptar una nueva autenticación de cliente con la clave prescrita. tener lugar. Dichas solicitudes fuera de la ventana permitida pueden usarse como detección de intentos de imitación y posiblemente iniciar algunas contramedidas (listas negras de IP, etc.).

    
respondido por el Dan Cornilescu 04.08.2016 - 10:03
0

Por lo que sé, lo que mencionaste es la única manera de hacer esto. La aplicación que almacena la clave es definitivamente un riesgo, pero hay varias maneras de evitarlo. Siempre puede usar el almacén de claves para almacenar la clave, en lugar de la codificación, forzando así un inicio de sesión único.

Además, debe considerar vincular una clave a un cliente, por lo tanto, si alguien imita, debe tener una capa de seguridad para verificar el cliente, la clave y los agentes de usuario para bloquear la solicitud inmediatamente. Tenga un caso de uso para volver a emitir o volver a asegurar que no se imiten las claves.

    
respondido por el Arun 04.08.2016 - 07:55
0

Si depende de dar tokens de autorización a sus clientes para que incluyan sus aplicaciones, siempre será teóricamente posible que alguien realice una ingeniería inversa de la aplicación y la extraiga. Para evitar esto, necesitará un mecanismo que no requiera un secreto dentro de la aplicación cliente. Eso es complicado. Aunque puedo sugerir algunas opciones para que pienses.

Una vez que haya entregado las credenciales, tiene un problema, no tiene control sobre la seguridad con que se almacenan. Además, si necesita que el usuario le envíe las credenciales, entonces alguien puede MITM su conexión y robar los tokens directamente sin preocuparse por la aplicación de ingeniería inversa.

Una forma de dificultar la extracción de su token de autorización es ocultarlo. Esto solo eleva el listón, pero no lo hace imposible, y para hacerlo tendría que mantener el control del secreto. Podría implementar una biblioteca que contenga la información secreta y que sea específica para cada cliente. Podría usar la biblioteca para comunicarse con sus servidores y es posible que ni siquiera tenga que decirle a su usuario la información secreta, simplemente podría estar incrustada en la biblioteca. Esto no resuelve el problema de alguien que realiza ingeniería inversa en su biblioteca, pero lo pone en control del nivel de ofuscación. Un inconveniente es que una vez que una persona rompe la ofuscación en la biblioteca, puede atacar cualquier biblioteca suya, a menos que escriba un código que haga que cada biblioteca sea significativamente diferente. Eso introduce su propio conjunto de problemas.

Esto puede desviarse ligeramente del alcance de su pregunta, pero está relacionado con la seguridad de su token, así que lo mencionaré. Para evitar el robo trivial del token a través del cable, es probable que no desee enviar el token directamente, en su lugar podría firmar el tráfico utilizando una función HMAC. Puede verificar la validez del mensaje calculando el HMAC del mensaje en el servidor y comparándolo con el HMAC enviado desde el cliente. Usaría el token como la clave para la función HMAC, de modo que solo alguien que conozca el token puede firmar el tráfico. Esto es mejor para la seguridad de su token porque nunca lo envía directamente al servidor, por lo que no puede ser interceptado ni robado directamente. Para obtener más información sobre HMACS, consulte esta pregunta: enlace

Ninguna solución de seguridad será inexpugnable, debe decidir cuánto le costará implementar frente a la probabilidad y el costo de estar comprometido.

    
respondido por el ThePragmatist 04.08.2016 - 16:15
0

Cotizándose:

  

No puedo averiguar cómo autenticar al cliente / usuario ... en el que no pueden poner su nombre de usuario y contraseña para autenticarse.

Ahora eso es un poco contradictorio, ¿no es así? ;)

Como han dicho otros, no puedes. Si una aplicación utiliza una clave de API, se puede descompilar como dices para obtener las claves y usarlas también.

Además de requerir una autenticación de usuario adecuada adicional, solo puede limitar el daño:

  • IPs de listas blancas / listas negras
  • limitación
  • detección de "actividad inusual" y su fuente
  • renovación de clave fácil
respondido por el dagnelies 08.08.2016 - 14:15