¿Cómo me aseguro de que mi API REST solo responda a solicitudes generadas por clientes confiables, en mi caso, mis propias aplicaciones móviles? Quiero evitar solicitudes no deseadas procedentes de otras fuentes. No quiero que los usuarios completen una clave de serie o lo que sea, debería suceder detrás de escena, después de la instalación y sin necesidad de interacción del usuario.
Hasta donde sé, HTTPS es solo para validar que el servidor con el que se está comunicando es quién dice que es. Por supuesto, voy a usar HTTPS para cifrar los datos.
¿Hay alguna manera de lograr esto?
Actualización: el usuario puede realizar acciones de solo lectura, que no requieren que el usuario inicie sesión, pero también pueden realizar acciones de escritura, que requieren que el usuario inicie sesión (Autenticación por token de acceso). En ambos casos, quiero que la API responda a las solicitudes que provienen solo de aplicaciones móviles confiables.
La API también se utilizará para registrar una nueva cuenta a través de la aplicación móvil.
Actualización 2: Parece que hay varias respuestas a esto, pero honestamente no sé cuál marcar como respuesta. Algunos dicen que se puede hacer, otros dicen que no.
Respuestas:
No puedes
Nunca puede verificar una entidad, ninguna entidad , ya sea una persona, un cliente de hardware o un cliente de software. Solo puedes verificar que lo que te están diciendo es correcto, luego asumir la honestidad .
Por ejemplo, ¿cómo sabe Google que estoy iniciando sesión en mi cuenta de Gmail? Ellos simplemente me piden un nombre de usuario y contraseña, verificar que , a continuación, asumir la honestidad , porque quién más tendría esa información? En algún momento, Google decidió que esto no era suficiente y agregó la verificación del comportamiento (en busca de un comportamiento extraño), pero eso todavía depende de que la persona realice el comportamiento y luego valide el comportamiento .
Esto es exactamente lo mismo con la validación del Cliente. Solo puede validar el comportamiento del Cliente, pero no el Cliente en sí.
Entonces, con SSL, puede verificar que el Cliente tenga un certificado válido o no, así que uno simplemente puede instalar su aplicación, obtener el Certificado y luego ejecutar todo el código nuevo.
Entonces la pregunta es: ¿Por qué es esto tan crítico? Si esto es una preocupación real, cuestionaría su elección de un cliente gordo. Tal vez debería ir con una aplicación web (para que no tenga que exponer su API).
Ver también: Derrota de la validación de certificados SSL para aplicaciones de Android
y: ¿Qué tan seguros son los certificados SSL del cliente en una aplicación móvil?
fuente
Estoy seguro de que se siente cómodo tratando con los inicios de sesión de los usuarios y con las comunicaciones a través de SSL, por lo que me centraré en lo que creo que es la parte más interesante de la pregunta: cómo asegurarse de que sus acciones de solo lectura: que no requieren que el usuario se autentique, ¿solo se aceptan desde sus propias aplicaciones cliente?
Antes que nada, existe la desventaja que fNek insinuó en una respuesta anterior: sus aplicaciones cliente están en manos de usuarios potencialmente hostiles. Pueden ser examinados, sus comunicaciones inspeccionadas, su código desmontado. Nada de lo que voy a sugerir le permitirá garantizar que alguien no realice ingeniería inversa a su cliente y abuse de su API REST. Pero debería poner una barrera frente a cualquier intento casual.
De todos modos, un enfoque común es:
por ejemplo, imagine una
GET
solicitud de/products/widgets
Digamos que el secreto del cliente es "OH_HAI_I_IZ_SECRET"
Concatenar el verbo HTTP, y la URL, y el secreto:
Y tome un hash SHA-1 de eso:
Luego envíelo junto, de modo que la solicitud sería para:
Finalmente, para evitar que alguien al menos reproduzca solicitudes individuales, tome también una marca de tiempo y agréguela a los parámetros y al hash. por ejemplo, ahora, en tiempo Unix, es 1384987891. Agregue eso a la concatenación:
Hash que:
Y enviar:
El servidor verificará el hash y también verificará que la marca de tiempo esté actualizada (por ejemplo, dentro de los 5 minutos para permitir que los relojes no estén perfectamente sincronizados)
¡Advertencia! Como estás hablando de aplicaciones móviles, existe un riesgo claro de que el teléfono de alguien tenga el reloj equivocado. O zona horaria incorrecta. O algo. Agregar el tiempo al hash probablemente romperá a algunos usuarios legítimos, así que use esa idea con precaución.
fuente
Para cualquier persona interesada, en Android PUEDE verificar que la solicitud que recibió se haya enviado desde su aplicación.
En resumen, cuando carga su aplicación en Google, la firma, con una clave única que solo conoce usted (y Google).
El proceso de verificación va (ish) así:
el blog completo que lo explica y cómo implementarlo se puede encontrar aquí: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html
fuente
Ok, vale la pena mencionar antes de comenzar que para la mayoría de las aplicaciones esto es demasiado exagerado. Para la mayoría de los casos de uso, simplemente tener un solo certificado o token válido es más que suficiente. Si implica hacer algo difícil como descompilar su aplicación, incluso la mayoría de los hackers no se molestarán a menos que proporcione algunos datos muy valiosos. Pero bueno, ¿dónde está la diversión en esa respuesta?
Entonces, lo que puede hacer es configurar una criptografía asimétrica similar a la firma digital utilizada para firmar programas. Cada aplicación puede tener un certificado individual emitido por una sola CA y verificado cuando su usuario se conecta. (ya sea cuando se registra por primera vez o cuando se instala por primera vez) Cuando se autentica ese certificado, puede asegurar aún más su aplicación al registrar ese certificado como válido para un identificador de dispositivo dado (como ID de Android )
fuente
Como @Morons mencionó en su respuesta, es muy difícil verificar la entidad en el otro extremo de la conexión.
La forma más sencilla de proporcionar cierto nivel de autenticidad es hacer que el servidor verifique algún secreto que solo la entidad real conocería. Para un usuario, puede ser un nombre de usuario y una contraseña. Para una pieza de software donde no hay usuario, puede incrustar un secreto.
El problema con estos enfoques es que debe confiar un poco en el cliente. Si alguien aplica ingeniería inversa a su aplicación o le roba su contraseña, puede pretender ser usted.
Puede tomar medidas para dificultar la extracción de la información secreta al ofuscarla en el ejecutable. Herramientas como ProGuard, que es un ofuscador para Java, pueden ayudar con esto, no sé mucho sobre la ofuscación en otros idiomas, pero es probable que haya herramientas similares. El uso de una conexión TLS ayuda a evitar que las personas espíen su tráfico, pero no evita un ataque MITM. La fijación puede ayudar a resolver ese problema.
Trabajo para una compañía llamada CriticalBlue (¡divulgación completa!) Que tiene un producto llamado Approov que trata de resolver este problema de confianza. Actualmente funciona para Android / iOS y proporciona un mecanismo para que nuestros servidores verifiquen la integridad de la aplicación cliente. Lo hace haciendo que el cliente calcule una respuesta a un desafío aleatorio. El cliente tiene que calcular la respuesta utilizando los atributos del paquete de la aplicación instalada que son difíciles de falsificar e incluye algunos sofisticados mecanismos anti-manipulación.
Devuelve un token que luego puede enviar como prueba de autenticidad a su API.
La diferencia importante con este enfoque es que, aunque sería posible deshabilitar la comprobación de autenticidad en el cliente, si lo hiciera no obtendría el token de autenticación que necesita para verificar su aplicación con el servidor. La biblioteca también está estrechamente unida a las características del ejecutable en el que se encuentra, por lo que sería muy difícil incrustarla en una aplicación falsa y hacer que funcione.
Hay un análisis de costo / beneficio que cualquier desarrollador de API debe hacer para decidir qué tan probable es que alguien intente piratear su API y cuán costoso puede ser. Una simple verificación secreta en la aplicación evita ataques triviales, pero protegerse contra un atacante más decidido es probablemente mucho más complicado y potencialmente costoso.
fuente
SSL asegurará el canal de comunicación.
El inicio de sesión exitoso emitirá un token de autenticación a través de una conexión cifrada.
El token de autenticación se pasará a su API REST en todas las solicitudes posteriores.
fuente
No sería demasiado seguro, pero podría agregar algún tipo de código secreto o incluso una firma digital. Desventaja: debe incluirse en la aplicación, lo que facilita su obtención si sabes lo que haces.
fuente
De hecho, puede usar SSL para autenticar tanto al cliente como al servidor. O, dicho de otra manera, "sí, puede usar certificados de cliente".
Tendrás que ...
Puede hacer que la aplicación móvil almacene el certificado donde lo desee. Dado que desea la autenticación específica de la aplicación, debe considerar almacenar el certificado en una ubicación de disco protegida (en Android, puede crear una tabla de "configuración" en su base de datos SQLite, y una fila para su certificado y otra para su clave privada) .
fuente