He estado desarrollando una aplicación que admitirá muchos usuarios. Lo que pasa es que no puedo entender cómo autenticar al cliente / usuario.
Estoy creando una aplicación como http://quickblox.com/ donde les daré credenciales a mis usuarios y los usarán para construir N aplicaciones en las que no pueden poner su nombre de usuario y contraseña para autenticarse.
Supongamos que va de la siguiente manera. (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 API y clave secreta) en las aplicaciones que creen, ¿qué sucede si alguien obtiene estas claves e intenta imitar al usuario? (Descompilando APK o buscando directamente en el código JavaScript.
¿Me equivoco en alguna parte?
Estoy confundido con el arquitecto de este mecanismo de usuario de tres niveles.
Respuestas:
He estado diseñando API REST durante los últimos años. Te estás preocupando demasiado. Recientemente, otro usuario en este foro hizo una pregunta, donde le preocupaba almacenar puntos finales URI en su código JavaScript del lado del cliente .
Se aplican las mismas reglas que se aplican al desarrollador de JavaScript. Si permite que personas externas integren su API, su API tiene la misma visibilidad que un sitio web normal y debe tratarla de la misma manera.
Cita de la respuesta original:
Debe diseñar los tokens de acceso de la aplicación para permitir solo las operaciones que desea permitir. Podría tener dos tipos de tokens de acceso:
Pero, ¿qué 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.
fuente
filtered data
(B) de su usuario . Ahora es posible, o hay alguna solución para evitar que un tercer usuario robe todos los datos (A + B) de mi usuario . ¿Tiene sentido?Su problema no es tanto técnico como comercial.
Digamos que tiene su API, que vende a sus clientes (los desarrolladores de la aplicación) por una tarifa plana de £ 100 al año, acceso ilimitado.
Bueno, 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 le permita vender su API sin que esté abierta al arbitraje.
Si solo restringe la cantidad de aplicaciones, un cliente puede crear una sola aplicación que acepte conexiones de otras aplicaciones y las transfiera.
Si limita a los usuarios, nuevamente, el cliente puede ocultar usuarios detrás de su propia autenticación y parecer un solo usuario.
Lo que debe hacer es pasar el costo de cada llamada 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 adoptar medidas para evitar que sus usuarios roben sus claves. En este caso, esconde tu API detrás de su propia API autenticada por el usuario.
fuente
Las otras respuestas parecen sugerir que el problema de almacenar un secreto en una aplicación en dispositivos de consumo no se puede resolver.
Claro que lo es.
Dos principios (se seguirán los detalles de implementación):
Dado que, si el cliente realiza una solicitud al punto final de autenticación con credenciales, y el servidor la autentica, el servidor puede generar un token temporal dinámico (temporal, lo que significa tiempo). Este token debe recordarse dentro del cliente y enviarse 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 a partir de 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 no autorizado a la API, aún necesitará autenticarse como cualquier otra persona.
fuente
Si tiene claves únicas por aplicación, puede usarlas solo durante una autenticación de conexión inicial, iniciada por el cliente, luego de lo cual cambia a un token de autenticación único por aplicación.
Su servidor cambia (lanza) el token para cada aplicación cliente de vez en cuando (periódicamente más / menos algún retraso difuso / aleatorio aleatorio, por ejemplo). El token móvil solo es conocido entre el servidor y el cliente autenticado.
Los nuevos tokens se devuelven a cuestas en las respuestas regulares. Cada vez que la respuesta contiene un nuevo token, la aplicación receptora debe cambiar para usarla en solicitudes posteriores.
Cada vez que el intercambio con un cliente no esté sincronizado (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 respaldado en la respuesta válida a la solicitud del cliente, para 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 permanece inactivo durante un intervalo más largo de lo esperado, que podría, por ejemplo, ser causado por una interrupción / reinicio del cliente con una nueva instancia que no tiene el token rodante.
Sería aún 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 imitar.
Tal esquema haría que imitar al menos fuera bastante difícil: el cliente que imita tendría que predecir exactamente la ventana cuando el cliente autorizado deja de enviar solicitudes el tiempo suficiente para que el servidor decida que está bien aceptar que se pueda realizar una nueva autenticación de cliente con la clave prescrita. Tales solicitudes fuera de la ventana permitida se pueden usar como detección de intentos de imitación y posiblemente iniciar algunas contramedidas (listas negras de IP, etc.).
fuente
Por lo que sé, lo que mencionaste es la única forma de hacer esto. La aplicación que almacena la clave definitivamente es un riesgo, pero hay varias formas de eludirla. Siempre puede usar el almacén de claves para almacenar la clave, en lugar de codificar, 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 de inmediato. Tenga un caso de uso para volver a emitir o asegurar que las claves no se imitan.
fuente
Si depende de dar tokens de autorización a sus clientes para que pongan 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 Sin embargo, puedo sugerirte algunas opciones para que pienses.
Tiene un problema una vez que ha entregado las credenciales, no tiene control sobre la seguridad con la que se almacenan. Además, si requiere que el usuario le envíe las credenciales, alguien puede MITM su conexión y robar los tokens directamente sin preocuparse por la ingeniería inversa de la aplicación.
Una forma de hacer que sea más difícil extraer su token de autorización es ofuscarlo. Esto solo sube el listón, pero no lo hace imposible, y para hacerlo tendrías que mantener el control del secreto. Puede implementar una biblioteca que contenga la información secreta y sea específica para cada cliente. Puede 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 que alguien realice ingeniería inversa en su biblioteca, pero sí le permite controlar el nivel de ofuscación. Un inconveniente es que una vez que una persona ha roto la ofuscación en la biblioteca, puede atacar cualquier biblioteca tuya, a menos que escribas un código que haga que cada biblioteca sea significativamente diferente. Eso introduce su propio conjunto de problemas.
Esto puede alejarse un poco del alcance de su pregunta, pero está relacionado con la seguridad de su token, por lo que lo mencionaré. Para evitar el robo trivial del token a través del cable, probablemente no desee enviar el token directamente, en su lugar, puede 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 de la función HMAC para que solo alguien que conozca el token pueda 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 y robado directamente. Para obtener más información sobre HMACS, consulte esta pregunta: /security/20129/how-and-when-do-i-use-hmac/20301
Ninguna solución de seguridad será inexpugnable, debe decidir cuánto le costará implementar frente a la probabilidad y el costo de verse comprometido.
fuente
Citando a ti mismo:
Ahora que es una contradicción, ¿no? ;)
Como otros dijeron, no puedes. Si una aplicación usa una clave API, se puede descompilar como usted dice para obtener la (s) clave (s) y usarla también.
Además de requerir una autenticación de usuario adecuada adicional, solo puede limitar el daño:
fuente