2010-08-28 39 views
43

Tengo una API de servicio web relajante, que está siendo utilizada por terceros diferentes. Parte de esa API está restringida (se necesita nombre de usuario/contraseña para acceder a ella). Me preguntaba ¿cuál sería la mejor forma de implementar la autenticación?Autenticación razonable del servicio web

Estoy usando https, por lo que la comunicación está encriptada. Tengo dos ideas:

  • Antes de que el usuario comience a usar el servicio (restringido), envía un nombre de usuario/contraseña usando POST (desde que se usan las credenciales https). Después de que el inicio de sesión sea exitoso, el servidor devuelve un valor aleatorio de un solo uso (nonce) que coincide con este nombre de usuario. Cuando se realiza la próxima solicitud, junto con un nombre de usuario, el cliente envía el código de acceso devuelto previamente. Los servidores coinciden con el nombre de usuario y el nonce y devuelven el nuevo nonce junto con los datos solicitados. Cada nueva solicitud usa new nonce. Básicamente, esta es una versión ligera de autenticación de acceso Digest.
  • Dado que esta API se utiliza de un tercero, el nombre de usuario/contraseña se podría usar para cada solicitud (restringida). Como https se está utilizando, se cifrarán. La caída de este enfoque es el hecho de que esto no cumpliría con Restful (el POST se usaría siempre).

Estoy mucho más cerca de elegir el primer enfoque (es compatible con Restful, es relativamente fácil de implementar, XML, json o html se puede usar sin cambiar nada), pero quería ver cuál es su opinión? ¿Qué recomienda: primero, segundo o algún tercer enfoque?

Btw, estoy usando Python en el lado del servidor.

Respuesta

6

Amazon web services lo hace bien, consulte la metodología para algunas ideas. Básicamente, hacen que los clientes encripten un encabezado http especial usando su contraseña.

Aquí está el enlace:

http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html

+0

La mejor respuesta por cualquier medida. ¡Si pudieras dar una buena introducción al algoritmo aquí mismo, estoy seguro de que obtendrías toneladas de votos en muy poco tiempo! Creo que uno de los aspectos más importantes es este: "Primero usa su clave de acceso secreta para crear una clave de firma. La clave de firma tiene un alcance en una región y servicio específicos. Además, la clave de firma expira siete días después de la creación. el alcance y el tiempo de vida de la clave de firma son limitados, sus datos corren menos riesgo si la clave de firma se ve comprometida ". – Domi

23

Una forma que he visto este hecho en las API (y la forma en que actualmente estoy implementando) es crear un recurso REST llamada Sesión que se crea a través de a POST que proporciona un nombre de usuario y contraseña.

Aquí es básicamente la forma en vez implementado:

POST /sessions { Username: "User", Password: "Password" } 

crear una sesión de tiempo limitado y devuelve el recurso de sesión que contiene el valor de clave de sesión y de caducidad. También puede devolver esto como un valor de cookie para la conveniencia de la implementación de clientes API.

DELETE /session/{id} 

Inmediatamente vence la sesión por lo que ya no se puede utilizar. Esto se usa para salidas explícitas.

Luego pido al usuario que adjunte la clave de sesión a través de un parámetro de consulta, aunque también puede permitir que se envíe a través de un valor de cookie, recomendaría permitir ambas.

Lo que prefiero de esto es que es extremadamente simple.

Obviamente, su escenario dictará de alguna manera cómo deben administrarse sus sesiones, tal vez no tengan un límite de tiempo y sean de duración indefinida, y tal vez estén codificadas o cifradas para mayor seguridad.

Si está utilizando HTTPS en todas partes, probablemente no tenga que preocuparse demasiado. Sin embargo, si desea utilizar HTTP, deberá usar algo así como un hash junto con una clave secreta y decir una marca de tiempo para generar una clave segura por solicitud. De esta forma, puede compartir la clave secreta a través de HTTPS y luego cambiar a HTTP para realizar más llamadas. Incluso si alguien logra olfatear la clave de una solicitud, puede caducar casi de inmediato y ser inútil.

Descargo de responsabilidad: No soy un experto en seguridad ;-).

+1

Si usa sesiones en el servidor, su API no es RESTful, porque el servidor tiene un estado. Cada solicitud debe contener todos los datos necesarios y el servidor no debe confiar en las sesiones. Guarde sus datos de sesión en un token web JSON que el cliente envía en un encabezado en cada solicitud. Puede empaquetar un objeto de usuario serializado, por ejemplo (así es como lo hago). – felixfbecker

+0

Esto parece un poco pedante y también supone que es importante que la autenticación sea estrictamente "RESTful". Enfoques como JWT resuelven esto sin embargo, si es necesario o importante para su aplicación hacer las cosas de esta manera. –

4

Suponiendo que el servicio nunca se consume en un navegador y la comunicación está cifrada de todos modos, no veo mal en una variación del segundo método: Añadir encabezados X para enviar nombre de usuario/contraseña con cada solicitud, por ejemplo:

GET /foo HTTP/1.1 
Host: www.bar.com 
X-MyUsername: foo 
X-MyPassword: bar 

Otra idea sería utilizar HTTP Basic Auth y simplemente enviar un Authorization: Basic base64(user:password) -Header. Es decir, si la conexión siempre está encriptada.

+0

¿Cómo implementa 'iniciar sesión' y 'cerrar sesión' en tal caso? –

+2

Creo que no hay 'inicio de sesión' ni 'cierre sesión' en este caso, ya que está enviando nombre de usuario/contraseña en cada solicitud. –

+0

La autenticación básica aún no es tan buena debido a la falsificación de solicitudes entre sitios. –

8

No hay ninguna razón para no solo usar la autenticación HTTP aquí.

Dicho esto, el concepto de POSTing para obtener un bloque de tiempo nonce puede funcionar bien. Pero son las motivaciones de por qué tendrías que pasar por ese aro adicional en primer lugar.

Esta técnica se consideró al utilizar un hash bcrypt para la contraseña original, debido al gasto real de validación de un usuario (si no lo sabe, bcrypt puede ajustarse para tomar un tiempo real significativo para realizar la función hash) . La elección fue proporcionar la opción de hacer que el servicio "inicie sesión" una vez usando la contraseña que pasaría por el proceso de validación costoso a través de bcrypt, y luego obtendría un token bloqueado en el tiempo a cambio de futuras solicitudes que omitirían el proceso bcrypt .

En el caso del proceso bcrypt, use HTTP Authentication, el servicio funcionaría tanto con la contraseña normal como con el token. De esa forma, el usuario siempre puede usar la contraseña para su servicio, pero simplemente se vuelve costoso. Entonces PUEDEN hacer esto, simplemente NO DEBERÍAN. Al servicio no le importa qué técnica de autenticación usa el cliente.

El servicio nonce se ofrece aparte para mejorar el rendimiento.

Aparte de eso, es una autenticación HTTP estándar, pero con un nuevo esquema.

+1

Una razón para no usar la autenticación HTTP es que el navegador la enviará automáticamente con cada solicitud, exponiéndolo a ataques CSRF. Sin embargo, usar un esquema de Autorización personalizado está bien. O usando un encabezado personalizado. –

Cuestiones relacionadas