Autenticación API REST

181

Estoy creando una aplicación que se alojará en un servidor. Quiero crear una API para la aplicación para facilitar la interacción desde cualquier plataforma (aplicación web, aplicación móvil). Lo que no entiendo es que cuando utilizo la API REST, ¿cómo autenticamos al usuario?

Por ejemplo, cuando un usuario ha iniciado sesión y luego quiere crear un tema del foro. ¿Cómo sabré que el usuario ya inició sesión?

Noor
fuente
44
Probablemente debería buscar "autenticación REST" aquí. Se ha cubierto en muchas otras preguntas.
Brian Kelly el
10
En pocas palabras, deje que el cliente envíe un nombre de usuario y una contraseña con cada solicitud utilizando HTTP Basic Auth (¡sobre SSL!), O autentíquese una vez para que el cliente tenga una sesión autenticada que caducará después de un período de inactividad (o como elija anular manejo de sesión de su marco web). Dicha sesión puede almacenarse en una cookie, o ser un parámetro pasado con cada solicitud (por ejemplo, JSESSIONID en tierra Java).
opiato
Consulte también Cómo controlar quién usa mi widget web .
Arjan
@opyate desde el punto de vista de la seguridad, no es realmente una buena idea manejar la sesión usando cookies en un caso de API REST, ya que los atacantes pueden enviar solicitudes sin el consentimiento del usuario. Es mejor incluir un hash o token de sesión en un encabezado HTTP (como Autorización).
s3v3n
1
@ s3v3n Corrígeme si me equivoco, pero tanto tu como mis sugerencias son solo diferentes formas de usar un combo de encabezado + almacenamiento local para lograr lo mismo. Es Authorizationencabezado + por ejemplo, navegador local, almacenamiento VS Cookieencabezado + almacenamiento estándar de cookies del navegador.
opiato el

Respuestas:

72

Puede usar HTTP Basic o Digest Authentication. Puede autenticar de forma segura a los usuarios utilizando SSL en la parte superior, sin embargo, ralentiza un poco la API.

  • Autenticación básica: utiliza la codificación Base64 en nombre de usuario y contraseña
  • Autenticación implícita: codifica el nombre de usuario y la contraseña antes de enviarlos a través de la red.

OAuth es lo mejor que puede obtener. Las ventajas que ofrece oAuth es un token revocable o expirable. Consulte lo siguiente sobre cómo implementar: Enlace de trabajo de los comentarios: https://www.ida.liu.se/~TDP024/labs/hmacarticle.pdf

ankitjaininfo
fuente
44
Lea esta pregunta y la respuesta proporcionada por Les Hazelwood (autor de Apache Shiro).
justin.hughey 03 de
1
Enlace útil sobre cómo protege Twitter su API REST: Seguridad de la API REST de Twitter
WildDev
Como esta es la respuesta aceptada, creo que es importante mencionar que también puede usar la autenticación implícita. Lea sobre las diferencias entre las autenticaciones Básica y Digest aquí: stackoverflow.com/questions/9534602/…
Rayee Roded
116

Por ejemplo, cuando un usuario ha iniciado sesión. Ahora digamos que el usuario desea crear un tema del foro, ¿Cómo sabré que el usuario ya ha iniciado sesión?

Piénselo: debe haber algún apretón de manos que le indique a su API "Crear foro" que esta solicitud actual es de un usuario autenticado. Dado que las API REST generalmente no tienen estado, el estado debe persistir en alguna parte . Su cliente que consume las API REST es responsable de mantener ese estado. Por lo general, tiene la forma de un token que se pasa desde el momento en que el usuario inició sesión. Si el token es bueno, su solicitud es buena.

Compruebe cómo Amazon AWS realiza las autenticaciones. Ese es un ejemplo perfecto de "pasar el dinero" de una API a otra.

* Pensé en agregar alguna respuesta práctica a mi respuesta anterior. Pruebe Apache Shiro (o cualquier biblioteca de autenticación / autorización). En pocas palabras, intente y evite la codificación personalizada. Una vez que haya integrado su biblioteca favorita (uso Apache Shiro, por cierto), puede hacer lo siguiente:

  1. Cree una API de inicio / cierre de sesión como: /api/v1/loginyapi/v1/logout
  2. En estas API de inicio y cierre de sesión, realice la autenticación con su tienda de usuario
  3. El resultado es un token (generalmente JSESSIONID) que se envía de vuelta al cliente (web, móvil, lo que sea)
  4. A partir de este momento, todas las llamadas posteriores realizadas por su cliente incluirán este token
  5. Digamos que su próxima llamada se realiza a una API llamada /api/v1/findUser
  6. Lo primero que hará este código API es verificar el token ("¿está autenticado este usuario?")
  7. Si la respuesta regresa como NO, entonces devuelve un Estado HTTP 401 al cliente. Déjelos manejarlo.
  8. Si la respuesta es SÍ, proceda a devolver el Usuario solicitado.

Eso es todo. Espero que esto ayude.

Kingz
fuente
Entonces, lo que estás describiendo es esencialmente una cookie de sesión, ¿verdad?
LordOfThePigs
sí, pero la sesión se "mantiene" en 2 lugares diferentes. Uno en el servidor API, otro en el navegador. La respuesta JSON (o lo que sea) de vuelta al inicio de sesión exitoso del navegador debe comunicar la identificación de la sesión en el servidor API nuevamente al navegador. Estas sesiones son administradas independientemente por sus respectivos agentes.
Kingz
11
Creo que Kingz estaba tratando de transmitir la idea de que el mecanismo para mantener la sesión es intencionalmente vago. Una cookie de sesión es solo una implementación de ese mecanismo.
justin.hughey 03 de
2
@Kingz, ¿qué pasa con la seguridad en esta solución, por ejemplo, si algún hacker olfatea el enlace con session_id y comienza a enviar solicitudes cuyo contenido corrige session_id? Podemos resolverlo agregando SSL a la conexión del servidor, pero ¿qué pasa con los clientes?
Ahmad Samilo
1
¿Cómo evitar el secuestro de sesión en el caso de man-in-the-middle-attrack?
m0z4rt
38
  1. Use HTTP Basic Auth para autenticar clientes, pero trate el nombre de usuario / contraseña solo como un token de sesión temporal .

    El token de sesión es solo un encabezado adjunto a cada solicitud HTTP, por ejemplo: Authorization: Basic Ym9ic2Vzc2lvbjE6czNjcmV0

    la cadena Ym9ic2Vzc2lvbjE6czNjcmV0 anterior es solo la cadena "bobsession1: s3cret" (que es un nombre de usuario / contraseña) codificada en Base64.

  2. Para obtener el token de sesión temporal anterior, proporcione una función de API (por ejemplo:) http://mycompany.com/apiv1/loginque toma el nombre de usuario maestro y la contraseña maestra como entrada, crea un nombre de usuario / contraseña de autenticación básica HTTP temporal en el lado del servidor y devuelve el token (por ejemplo: Ym9ic2Vzc2lvbjE6czNjcmV0). Este nombre de usuario / contraseña debe ser temporal, debe expirar después de 20 minutos más o menos.

  3. Para mayor seguridad, asegúrese de que su servicio REST se sirva a través de HTTPS para que la información no se transfiera en texto sin formato

Si está en Java, la biblioteca Spring Security proporciona un buen soporte para implementar el método anterior

gerrytan
fuente
1
¿Por qué debería caducar después de 20 min? ¿Qué pasa si se trata de un sitio web como Facebook en el que el inicio de sesión es hasta que el usuario cierra sesión?
Dejell
1
@dejel Estaba bajo la suposición de que "sesión" es de naturaleza temporal. Es común que caduque si el usuario está
inactivo
¿Para qué sirve el Base64? Podrías devolver la contraseña temporal. En ambos casos, lo que realmente importa es que esta contraseña temporal sea segura. Consulte security.stackexchange.com/a/19686/72945
e18r el
7

Creo que el mejor enfoque es usar OAuth2. Búscalo en Google y encontrarás muchas publicaciones útiles para ayudarte a configurarlo.

Será más fácil desarrollar aplicaciones cliente para su API desde una aplicación web o una móvil.

Espero que te ayude.

Paulo Henrique
fuente
2
Lea esta pregunta y la respuesta de Les Hazelwood (autor de Apache Shiro).
justin.hughey 03 de
0

He estado usando la autenticación JWT. Funciona bien en mi aplicación.

Hay un método de autenticación que requerirá las credenciales del usuario. Este método valida las credenciales y devuelve un token de acceso en caso de éxito.

Este token debe enviarse a cualquier otro método en mi API web en el encabezado de la solicitud.

Es bastante fácil de implementar y muy fácil de probar.

Arthur Medeiros
fuente