Visión general
Estoy buscando crear una API (REST) para mi aplicación. El propósito inicial / primario será el consumo de aplicaciones móviles (iPhone, Android, Symbian, etc.). He estado buscando diferentes mecanismos de autenticación y autorización para API basadas en web (estudiando otras implementaciones). Tengo la cabeza concentrada en la mayoría de los conceptos fundamentales, pero todavía estoy buscando orientación en algunas áreas. Lo último que quiero hacer es reinventar la rueda, pero no encuentro ninguna solución estándar que se ajuste a mis criterios (sin embargo, mis criterios pueden estar equivocados, así que siéntete libre de criticar eso también). Además, quiero que la API sea la misma para todas las plataformas / aplicaciones que la consumen.
oAuth
Seguiré adelante y rechazaré mi objeción a oAuth, ya que sé que probablemente será la primera solución ofrecida. Para aplicaciones móviles (o más específicamente aplicaciones no web), parece incorrecto abandonar la aplicación (para ir a un navegador web) para la autenticación. Además, no hay forma (que yo sepa) de que el navegador devuelva la devolución de llamada a la aplicación (especialmente multiplataforma). Conozco un par de aplicaciones que hacen eso, pero se siente mal y da un descanso en la aplicación UX.
Requisitos
- El usuario ingresa el nombre de usuario / contraseña en la aplicación.
- Cada llamada a la API se identifica mediante la aplicación de llamada.
- Los gastos generales se mantienen al mínimo y el aspecto de autenticación es intuitivo para los desarrolladores.
- El mecanismo es seguro tanto para el usuario final (sus credenciales de inicio de sesión no están expuestas) como para el desarrollador (sus credenciales de aplicación no están expuestas).
- Si es posible, no requiera https (de ninguna manera es un requisito difícil).
Mis pensamientos actuales sobre la implementación
Un desarrollador externo solicitará una cuenta API. Recibirán un apikey y un apisecret. Cada solicitud requerirá como mínimo tres parámetros.
- apikey - dada al desarrollador en el registro
- marca de tiempo: funciona como un identificador único para cada mensaje para una apikey dada
- hash: un hash de la marca de tiempo + el apisecreto
Se requiere que la apikey identifique la aplicación que emite la solicitud. La marca de tiempo actúa de manera similar a oauth_nonce y evita / mitiga los ataques de repetición. El hash asegura que la solicitud fue emitida realmente por el propietario de la apikey dada.
Para las solicitudes autenticadas (las que se realizan en nombre de un usuario), todavía estoy indeciso entre ir con una ruta access_token o un combo de hash de nombre de usuario y contraseña. De cualquier manera, en algún momento se requerirá un combo de nombre de usuario / contraseña. Entonces, cuando lo haga, se usará un hash de varias piezas de información (apikey, apisecret, timestamp) + la contraseña. Me encantaría recibir comentarios sobre este aspecto. Para su información, primero tendrían que cambiar la contraseña, ya que no almaceno las contraseñas en mi sistema sin hash.
Conclusión
Para su información, esta no es una solicitud de cómo construir / estructurar la API en general, solo cómo manejar la autenticación y la autorización únicamente desde una aplicación.
Pensamientos aleatorios / preguntas extra
Para las API que solo requieren una apikey como parte de la solicitud, ¿cómo puede evitar que alguien que no sea el propietario de la apikey pueda ver la apikey (ya que se envió en claro) y realizar solicitudes excesivas para superar los límites de uso? Quizás acabo de pensar en esto, pero ¿no debería haber algo para autenticar que se verificó una solicitud al propietario de la apikey? En mi caso, ese era el propósito del apisecreto, nunca se muestra / transmite sin ser hash.
Hablando de hashes, ¿qué pasa con md5 vs hmac-sha1? ¿Realmente importa cuando todos los valores se combinan con datos suficientemente largos (es decir, apisecret)?
Anteriormente había estado considerando agregar una sal por usuario / fila al hash de contraseña de mis usuarios. Si tuviera que hacer eso, ¿cómo podría la aplicación ser capaz de crear un hash coincidente sin conocer la sal utilizada?
Respuestas:
La forma en que pienso hacer la parte de inicio de sesión de esto en mis proyectos es:
antes de iniciar sesión, el usuario solicita una
login_token
del servidor. Estos se generan y almacenan en el servidor a pedido, y probablemente tengan una vida útil limitada.para iniciar sesión, la aplicación calcula el hash de la contraseña de los usuarios, luego usa la contraseña
login_token
para obtener un valor, luego devuelvelogin_token
el hash combinado y el hash.El servidor comprueba si
login_token
es el que ha generado, eliminándolo de su lista de correos válidoslogin_token
. Luego, el servidor combina el hash almacenado de la contraseña del usuario con ellogin_token
y se asegura de que coincida con el token combinado enviado. Si coincide, ha autenticado a su usuario.Las ventajas de esto son que nunca almacena la contraseña del usuario en el servidor, la contraseña nunca se pasa en claro, el hash de contraseña solo se pasa en claro en la creación de la cuenta (aunque puede haber formas de evitar esto), y debería ser a salvo de ataques de repetición ya que
login_token
se elimina de la base de datos en uso.fuente
Esa es una gran cantidad de preguntas en una, creo que algunas personas no lograron leer hasta el final :)
Mi experiencia con la autenticación del servicio web es que las personas generalmente la diseñan en exceso, y los problemas son los mismos que encontraría en una página web. Las posibles opciones muy simples incluirían https para el paso de inicio de sesión, devolver un token, requerir que se incluya con futuras solicitudes. También puede usar la autenticación básica http y simplemente pasar cosas en el encabezado. Para mayor seguridad, gire / caduque los tokens con frecuencia, verifique que las solicitudes provengan del mismo bloque de IP (esto podría ser complicado, ya que los usuarios móviles se mueven entre celdas), combínelas con la clave API o similar. Alternativamente, realice el paso de "clave de solicitud" de oauth (alguien ya sugirió esto en una respuesta anterior y es una buena idea) antes de autenticar al usuario, y utilícelo como una clave requerida para generar el token de acceso.
Una alternativa que aún no he usado, pero que he escuchado mucho sobre como una alternativa amigable para dispositivos de oAuth es XAUTH . Eche un vistazo y si lo usa, me interesaría saber cuáles son sus impresiones.
Para el hashing, sha1 es un poco mejor, pero no se obsesione con eso; lo que sea que los dispositivos puedan implementar fácilmente (y rápidamente en un sentido de rendimiento) probablemente esté bien.
Espero que ayude, buena suerte :)
fuente
Entonces, ¿lo que buscas es algún tipo de mecanismo de autenticación del lado del servidor que maneje los aspectos de autenticación y autorización de una aplicación móvil?
Suponiendo que este sea el caso, entonces lo abordaría de la siguiente manera (pero solo porque soy un desarrollador de Java, por lo que un chico de C # lo haría de manera diferente):
El servicio RESTful de autenticación y autorización
La biblioteca / aplicación de seguridad del lado del cliente
Entonces, ahora que la vista desde 30,000 pies está completa, ¿cómo lo haces? Bueno, no es tan difícil crear un sistema de autenticación y autorización basado en las tecnologías enumeradas en el lado del servidor con un cliente de navegador. En combinación con HTTPS, los marcos proporcionarán un proceso seguro basado en un token compartido (generalmente presentado como una cookie) generado por el proceso de autenticación y utilizado siempre que el usuario desee hacer algo. El cliente presenta este token al servidor cada vez que se realiza una solicitud.
En el caso de la aplicación móvil local, parece que está buscando una solución que haga lo siguiente:
Hagas lo que hagas, no intentes inventar tu propio protocolo de seguridad ni uses la seguridad por la oscuridad. Nunca podrá escribir un algoritmo mejor para esto que los que están actualmente disponibles y son gratuitos. Además, las personas confían en algoritmos bien conocidos. Entonces, si dice que su biblioteca de seguridad proporciona autorización y autenticación para aplicaciones móviles locales que utilizan una combinación de tokens cifrados SSL, HTTPS, SpringSecurity y AES, inmediatamente tendrá credibilidad en el mercado.
Espero que esto ayude, y buena suerte con tu empresa. Si desea más información, hágamelo saber: he escrito bastantes aplicaciones web basadas en Spring Security, ACL y similares.
fuente
Twitter abordó el problema de la aplicación externa en oAuth al admitir una variante que llaman xAuth . Desafortunadamente, ya hay una gran cantidad de otros esquemas con este nombre, por lo que puede ser confuso resolverlo.
El protocolo es oAuth, excepto que omite la fase de token de solicitud y simplemente emite inmediatamente un par de tokens de acceso al recibir un nombre de usuario y contraseña. (A partir del paso E aquí .) Esta inicial solicitud y respuesta deben ser aseguradas- envía el nombre de usuario y la contraseña en texto sin formato y recibe el token de acceso y el token secreto. Una vez que se ha configurado el par de tokens de acceso, si el intercambio inicial de tokens fue a través del modelo oAuth o el modelo xAuth es irrelevante tanto para el cliente como para el servidor durante el resto de la sesión. Esto tiene la ventaja de que puede aprovechar la infraestructura existente de oAuth y tener casi la misma implementación para aplicaciones móviles / web / de escritorio. La principal desventaja es que la aplicación tiene acceso al nombre de usuario y contraseña del cliente, pero parece que sus requisitos exigen este enfoque.
En cualquier caso, me gustaría estar de acuerdo con su intuición y la de varios otros respondedores aquí: no intente construir algo nuevo desde cero. Los protocolos de seguridad pueden ser fáciles de iniciar, pero siempre son difíciles de hacer bien, y cuanto más intrincados se vuelven, es menos probable que sus desarrolladores externos puedan implementarlos. Su protocolo hipotético es muy similar a o (x) Auth - api_key / api_secret, nonce, sha1 hashing - pero en lugar de poder usar una de las muchas bibliotecas existentes que sus desarrolladores necesitarán para crear sus propias bibliotecas.
fuente
Súper tarde a la fiesta, pero quería agregar algunos puntos adicionales a tener en cuenta para cualquier persona interesada en este tema. Trabajo para una empresa que hace soluciones de seguridad de API móvil ( aproov ), por lo que toda esta área es definitivamente relevante para mis intereses.
Para empezar, lo más importante a tener en cuenta al tratar de proteger una API móvil es cuánto vale para usted . La solución correcta para un banco es diferente a la solución correcta para alguien que solo hace cosas por diversión.
En la solución propuesta, usted menciona que se requerirá un mínimo de tres parámetros:
La implicación de esto es que para algunas llamadas API no se requiere nombre de usuario / contraseña. Esto puede ser útil para aplicaciones en las que no desea forzar un inicio de sesión (por ejemplo, navegar en tiendas en línea).
Este es un problema ligeramente diferente al de la autenticación de usuario y se parece más a la autenticación o certificación del software. No hay usuario, pero aún así desea asegurarse de que no haya acceso malicioso a su API. Por lo tanto, utiliza su secreto API para firmar el tráfico e identificar el código que accede a la API como genuino. El problema potencial con esta solución es que luego tiene que revelar el secreto dentro de cada versión de la aplicación. Si alguien puede extraer el secreto, puede usar su API, suplantando su software pero haciendo lo que quiera.
Para contrarrestar esa amenaza, hay muchas cosas que puede hacer dependiendo de cuán valiosos sean los datos. Ofuscación es una forma sencilla de dificultar la extracción del secreto. Hay herramientas que harán eso por usted, más aún para Android, pero aún debe tener un código que genere su hash y una persona lo suficientemente capacitada siempre puede llamar a la función que hace el hash directamente.
Otra forma de mitigar el uso excesivo de una API que no requiere un inicio de sesión es limitar el tráfico e identificar y bloquear potencialmente las direcciones IP sospechosas. La cantidad de esfuerzo que desee realizar dependerá en gran medida de cuán valiosos sean sus datos.
Más allá de eso, puede comenzar fácilmente a ingresar al dominio de mi trabajo diario. De todos modos, es otro aspecto de la seguridad de las API que creo que es importante y que quería marcar.
fuente