Pregunta

¿Qué significa la autenticación RESTful y cómo funciona? No puedo encontrar una buena descripción general en Google. Lo único que entiendo es que pasa la clave de sesión (remeberal) en la URL, pero esto podría ser terriblemente incorrecto.

¿Fue útil?

Solución

Cómo manejar la autenticación en una arquitectura RESTful Cliente-Servidor es un tema de debate.

Comúnmente, se puede lograr, en el mundo SOA sobre HTTP a través de:

  • autenticación básica HTTP sobre HTTPS;
  • Cookies y gestión de sesiones;
  • Token en encabezados HTTP (por ejemplo, OAuth 2.0 + JWT);
  • Autenticación de consulta con parámetros de firma adicionales.

Tendrá que adaptar, o incluso mezclar mejor esas técnicas, para que coincida con la arquitectura de su software en el mejor de los casos.

Cada esquema de autenticación tiene sus propios PRO y CON, dependiendo del propósito de su política de seguridad y arquitectura de software.

Autenticación básica HTTP sobre HTTPS

Esta primera solución, basada en el protocolo HTTPS estándar, es utilizada por la mayoría de los servicios web.

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Es fácil de implementar, está disponible de forma predeterminada en todos los navegadores, pero tiene algunos inconvenientes conocidos, como la horrible ventana de autenticación que se muestra en el Navegador, que persistirá (no hay una función similar a LogOut aquí), algunos servidores adicionales El consumo de CPU y el hecho de que el nombre de usuario y la contraseña se transmiten (a través de HTTPS) al servidor (debería ser más seguro permitir que la contraseña permanezca solo en el lado del cliente, durante la entrada del teclado, y se almacene como hash seguro en el servidor).

Podemos usar Autenticación implícita , pero también requiere HTTPS, ya que es vulnerable a < a href = "http://en.wikipedia.org/wiki/Man-in-the-middle_attack" rel = "noreferrer"> MiM o Replay ataques, y es específico de HTTP.

Sesión a través de cookies

Para ser honesto, una sesión administrada en el servidor no es realmente sin estado.

Una posibilidad podría ser mantener todos los datos dentro del contenido de las cookies. Y, por diseño, la cookie se maneja en el lado del servidor (el cliente, de hecho, ni siquiera intenta interpretar estos datos de la cookie: solo la devuelve al servidor en cada solicitud sucesiva). Pero estos datos de cookies son datos de estado de la aplicación, por lo que el cliente debe administrarlos, no el servidor, en un mundo sin estado puro.

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

La técnica de cookies en sí está vinculada a HTTP, por lo que no es realmente RESTful, que debería ser independiente del protocolo, en mi humilde opinión. Es vulnerable a MiM o Replay ataques.

Otorgado a través de token (OAuth2)

Una alternativa es colocar un token dentro de los encabezados HTTP para que la solicitud se autentique. Esto es lo que hace OAuth 2.0, por ejemplo. Consulte el RFC 6749 :

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

En resumen, esto es muy similar a una cookie y sufre los mismos problemas: no tiene estado, depende de los detalles de transmisión HTTP y está sujeto a muchas debilidades de seguridad , incluidos MiM y Replay, por lo que solo se debe usar sobre HTTPS. Normalmente, un JWT se usa como token.

Autenticación de consulta

La autenticación de consulta consiste en firmar cada solicitud RESTful a través de algunos parámetros adicionales en el URI. Consulte este artículo de referencia .

Se definió como tal en este artículo:

  

Todas las consultas REST deben autenticarse firmando los parámetros de la consulta   ordenados en minúsculas, orden alfabético usando la credencial privada   como el token de firma. La firma debe ocurrir antes de que la URL codifique   cadena de consulta.

Esta técnica es quizás la más compatible con un Stateles

Otros consejos

Dudo si la gente grita con entusiasmo "Autenticación HTTP" alguna vez intenté crear una aplicación basada en navegador (en lugar de un servicio web de máquina a máquina) con REST (sin intención de ofender, simplemente no creo que hayan enfrentado las complicaciones).

Los problemas que encontré al usar la autenticación HTTP en los servicios RESTful que producen páginas HTML para ver en un navegador son:

    El usuario
  • generalmente obtiene un cuadro de inicio de sesión feo hecho por el navegador, que es muy poco amigable para el usuario. no puede agregar recuperación de contraseña, cuadros de ayuda, etc.
  • cerrar sesión o iniciar sesión con un nombre diferente es un problema: los navegadores seguirán enviando información de autenticación al sitio hasta que cierre la ventana
  • los tiempos de espera son difíciles

Un artículo muy perspicaz que aborda estos puntos por punto es aquí , pero esto resulta en un lote de hackers de JavaScript específicos del navegador, soluciones alternativas para soluciones alternativas, etc. Como tal, tampoco es compatible con versiones anteriores, por lo que requerirá un mantenimiento constante a medida que se publiquen nuevos navegadores. No considero ese diseño limpio y claro, además siento que es mucho trabajo extra y dolor de cabeza solo para poder mostrar con entusiasmo mi insignia REST a mis amigos.

Creo que las cookies son la solución. Pero espera, las galletas son malvadas, ¿no? No, no lo son, la forma en que las cookies se usan a menudo es mala. Una cookie en sí misma es solo una parte de la información del lado del cliente, al igual que la información de autenticación HTTP que el navegador registraría mientras navega. Y esta pieza de información del lado del cliente se envía al servidor en cada solicitud, de nuevo al igual que lo sería la información de autenticación HTTP. Conceptualmente, la única diferencia es que el contenido de esta parte del estado del lado del cliente puede ser determinado por el servidor como parte de su respuesta.

Al hacer que las sesiones sean un recurso RESTful con solo las siguientes reglas:

  • Una sesión asigna una clave a una identificación de usuario (y posiblemente una marca de tiempo de última acción para tiempos de espera)
  • Si existe una sesión , eso significa que la clave es válida.
  • Iniciar sesión significa PUBLICAR en / sesiones, una nueva clave se configura como una cookie
  • Cerrar sesión significa ELIMINAR / sesiones / {clave} (con la POST sobrecargada, recuerde, somos un navegador, y HTML 5 todavía es un largo camino por recorrer)
  • La autenticación se realiza enviando la clave como una cookie en cada solicitud y verificando si la sesión existe y es válida

La única diferencia con la autenticación HTTP, ahora, es que la clave de autenticación es generada por el servidor y enviada al cliente que la sigue enviando, en lugar de que el cliente la compute a partir de las credenciales ingresadas.

converter42 agrega que cuando se usa https (que deberíamos), es importante que la cookie tenga su bandera de seguridad configurada para que la información de autenticación nunca se envíe a través de una conexión no segura. Gran punto, no lo había visto yo mismo.

Creo que esta es una solución suficiente que funciona bien, pero debo admitir que no soy lo suficientemente experto en seguridad para identificar posibles agujeros en este esquema; todo lo que sé es que cientos de aplicaciones web no RESTful utilizan esencialmente el mismo protocolo de inicio de sesión ($ _SESSION en PHP, HttpSession en Java EE, etc.). El contenido del encabezado de la cookie simplemente se usa para abordar un recurso del lado del servidor, al igual que un lenguaje de aceptación podría usarse para acceder a los recursos de traducción, etc. Siento que es lo mismo, pero tal vez otros no. ¿Qué les parece, chicos?

Ya se ha dicho lo suficiente sobre este tema por buena gente aquí. Pero aquí están mis 2 centavos.

Hay 2 modos de interacción:

  1. humano a máquina (HTM)
  2. máquina a máquina (MTM)

La máquina es el denominador común, expresado como las API REST, y los actores / clientes son humanos o máquinas.

Ahora, en una arquitectura verdaderamente RESTful, el concepto de apatridia implica que todos los estados de aplicación relevantes (es decir, los estados del lado del cliente) deben suministrarse con todas y cada una de las solicitudes. Por relevante, se entiende que lo que sea requerido por la API REST para procesar la solicitud y servir una respuesta adecuada.

Cuando consideramos esto en el contexto de las aplicaciones de persona a máquina, "basado en navegador" Como Skrebbel señala anteriormente, esto significa que la aplicación (web) que se ejecuta en el navegador deberá enviar su estado y la información relevante con cada solicitud que realice a las API REST de back-end.

Considere esto: tiene un activo expuesto de plataforma de datos / información de las API REST. Quizás tenga una plataforma de BI de autoservicio que maneje todos los cubos de datos. Pero desea que sus clientes (humanos) accedan a esto a través de (1) aplicación web, (2) aplicación móvil y (3) alguna aplicación de terceros. Al final, incluso la cadena de MTM conduce a HTM, correcto. De modo que los usuarios humanos permanecen en la cúspide de la cadena de información.

En los primeros 2 casos, tiene un caso para la interacción de persona a máquina, siendo la información realmente consumida por un usuario humano. En el último caso, tiene un programa de máquina que consume las API REST.

El concepto de autenticación se aplica en todos los ámbitos. ¿Cómo diseñarás esto para que se acceda a tus API REST de manera uniforme y segura? A mi modo de ver esto, hay 2 formas:

Way-1:

  1. No hay inicio de sesión, para empezar. Cada solicitud realiza el inicio de sesión
  2. El cliente envía sus parámetros de identificación + la solicitud específica parámetros con cada solicitud
  3. La API REST los toma, da la vuelta, hace ping al almacén de usuarios (sea lo que sea) y confirma la autenticación
  4. Si se establece la autenticación, atiende la solicitud; de lo contrario, niega con el código de estado HTTP apropiado
  5. Repita lo anterior para cada solicitud en todas las API REST en su catálogo

Way-2:

  1. El cliente comienza con una solicitud de autenticación
  2. Una API REST de inicio de sesión manejará todas esas solicitudes
  3. Toma parámetros de autenticación (clave API, uid / pwd o lo que sea elegir) y verifica la autenticación en el almacén de usuarios (LDAP, AD o MySQL DB, etc.)
  4. Si se verifica, crea un token de autenticación y lo devuelve al cliente / llamante
  5. La persona que llama luego envía este token de autenticación + solicita parámetros específicos con cada solicitud posterior a otras API REST comerciales, hasta que se cierre la sesión o hasta que expire el contrato de arrendamiento

Claramente, en Way-2, las API REST necesitarán una forma de reconocer y confiar en el token como válido. La API de inicio de sesión realizó la verificación de autenticación y, por lo tanto, esa "clave de valet" necesita que otras API REST confíen en su catálogo.

Esto, por supuesto, significa que la clave / token de autenticación deberá almacenarse y compartirse entre las API REST. Este repositorio de tokens de confianza compartido puede ser local / federado, lo que permite que las API REST de otras organizaciones confíen entre sí.

Pero estoy divagando.

El punto es, un '' estado '' (sobre el estado autenticado del cliente) debe mantenerse y compartirse para que todas las API REST puedan crear un círculo de confianza. Si no hacemos esto, que es el Way-1, debemos aceptar que se debe realizar un acto de autenticación para cualquier / todas las solicitudes que ingresen.

La autenticación es un proceso que requiere muchos recursos. Imagine ejecutar consultas SQL, para cada solicitud entrante, en su tienda de usuarios para verificar la coincidencia de uid / pwd. O, para cifrar y realizar hash matche

Aquí hay una solución de autenticación verdaderamente y completamente RESTful:

  1. Cree un par de claves pública / privada en el servidor de autenticación.
  2. Distribuya la clave pública a todos los servidores.
  3. Cuando un cliente se autentica:

    3.1. emita un token que contenga lo siguiente:

    • Tiempo de caducidad
    • nombre de usuario (opcional)
    • IP de usuarios (opcional)
    • hash de una contraseña (opcional)

    3.2. Cifre el token con la clave privada.

    3.3. Envíe el token cifrado al usuario.

  4. Cuando el usuario accede a cualquier API, también debe pasar su token de autenticación.

  5. Los servidores pueden verificar que el token sea válido descifrándolo con la clave pública del servidor de autenticación.

Esta es una autenticación sin estado / RESTful.

Tenga en cuenta que si se incluyera un hash de contraseña, el usuario también enviaría la contraseña no cifrada junto con el token de autenticación. El servidor pudo verificar que la contraseña coincidía con la contraseña que se utilizó para crear el token de autenticación mediante la comparación de hashes. Sería necesaria una conexión segura usando algo como HTTPS. Javascript en el lado del cliente podría manejar la obtención de la contraseña del usuario y almacenarla en el lado del cliente, ya sea en la memoria o en una cookie, posiblemente encriptada con la clave pública del servidor.

Para ser honesto, he visto excelentes respuestas aquí, pero algo que me molesta un poco es cuando alguien llevará todo el concepto de Stateless a un extremo donde se vuelve dogmático. Me recuerda a esos viejos fanáticos de Smalltalk que solo querían adoptar OO puro y si algo no es un objeto, entonces lo estás haciendo mal. Dame un descanso.

Se supone que el enfoque RESTful le facilitará la vida y reducirá los gastos generales y el costo de las sesiones, trate de seguirlo, ya que es una buena idea, pero en el momento en que sigue una disciplina (cualquier disciplina / directriz) extremo donde ya no proporciona el beneficio para el que estaba destinado, entonces lo estás haciendo mal. Algunos de los mejores lenguajes actuales tienen programación funcional y orientación a objetos.

Si la forma más fácil de resolver su problema es almacenar la clave de autenticación en una cookie y enviarla al encabezado HTTP, entonces hágalo, simplemente no la abuse. Recuerde que las sesiones son malas cuando se vuelven pesadas y grandes, si toda su sesión consiste en una cadena corta que contiene una clave, entonces ¿cuál es el problema?

Estoy abierto a aceptar correcciones en los comentarios, pero no veo el punto (hasta ahora) en hacer nuestras vidas miserables para evitar simplemente mantener un gran diccionario de hashes en nuestro servidor.

En primer lugar, un servicio web RESTful es STATELESS (o, en otras palabras, SESSIONLESS ). Por lo tanto, un servicio RESTful no tiene ni debe tener un concepto de sesión o cookies involucrados. La forma de autenticar o autorizar en el servicio RESTful es usar el encabezado de Autorización HTTP como se define en las especificaciones HTTP RFC 2616. Cada solicitud debe contener el encabezado de Autorización HTTP, y la solicitud debe enviarse a través de una conexión HTTP (SSL). Esta es la forma correcta de autenticar y verificar la autorización de solicitudes en un servicio web RESTful HTTP. He implementado un servicio web RESTful para la aplicación Cisco PRIME Performance Manager en Cisco Systems. Y como parte de ese servicio web, también he implementado autenticación / autorización.

Rubens Gomes.

Ciertamente no se trata de " claves de sesión " ya que generalmente se usa para referirse a la autenticación sin sesión que se realiza dentro de todas las restricciones de REST. Cada solicitud se describe a sí misma y contiene suficiente información para autorizar la solicitud por sí sola sin ningún estado de aplicación del lado del servidor.

La forma más fácil de abordar esto es comenzando con los mecanismos de autenticación integrados de HTTP en RFC 2617 .

El artículo 'muy perspicaz' mencionado por @skrebel ( http://www.berenddeboer.net /rest/authentication.html ) analiza un método de autenticación complicado pero realmente roto.

Puede intentar visitar la página (que se supone que es visible solo para el usuario autenticado) http://www.berenddeboer.net/rest/site/authenticated.html sin ninguna credencial de inicio de sesión.

(Lo siento, no puedo comentar la respuesta)

Yo diría que REST y autenticación simplemente no se mezclan. REST significa sin estado pero 'autenticado' es un estado. No puede tenerlos a ambos en la misma capa. Si eres un defensor RESTful y desapruebas a los estados, entonces tienes que ir con HTTPS (es decir, dejar el problema de seguridad en otra capa).

Creo que la autenticación tranquila implica el paso de un token de autenticación como parámetro en la solicitud. Ejemplos son el uso de apikeys por api's. No creo que el uso de cookies o autenticación HTTP califique.

Actualización el 16-feb-2019

El enfoque mencionado anteriormente a continuación es esencialmente "Credencial de contraseña del propietario del recurso" tipo de concesión de OAuth2.0 . Esta es una manera fácil de comenzar a funcionar. Sin embargo, con este enfoque, todas las aplicaciones de la organización terminarán con sus propios mecanismos de autenticación y autorización. El enfoque recomendado es " Código de autorización " tipo de subvención Además, en mi respuesta anterior a continuación, recomendé el localStorage del navegador para almacenar tokens de autenticación. Sin embargo, he llegado a creer que la cookie es la opción correcta para este propósito. He detallado mis razones, el enfoque de implementación del tipo de concesión de código de autorización, las consideraciones de seguridad, etc. en esta respuesta de StackOverflow .


Creo que el siguiente enfoque se puede utilizar para la autenticación del servicio REST:

  1. Cree una API RESTful de inicio de sesión para aceptar el nombre de usuario y la contraseña para la autenticación. Use el método HTTP POST para evitar el almacenamiento en caché y SSL para la seguridad durante el tránsito En una autenticación exitosa, la API devuelve dos JWT: un token de acceso (validez más corta, digamos 30 minutos) y un token de actualización (validez más larga, digamos 24 horas)
  2. El cliente (una IU basada en web) almacena los JWT en el almacenamiento local y en cada llamada API posterior pasa el token de acceso en " Autorización: portador # token de acceso " encabezado
  3. La API verifica la validez del token verificando la firma y la fecha de vencimiento. Si el token es válido, verifique si el usuario (interpreta el '' sub '' reclamo en JWT como nombre de usuario) tiene acceso a la API con una búsqueda de caché. Si el usuario está autorizado para acceder a la API, ejecute la lógica empresarial
  4. Si el token ha caducado, la API devuelve el código de respuesta HTTP 400
  5. El cliente, al recibir 400/401, invoca otra API REST con el token de actualización en "Autorización: portador # token de actualización" encabezado para obtener un nuevo token de acceso.
  6. Al recibir la llamada con token de actualización, verifique si el token de actualización es válido verificando la firma y la fecha de vencimiento. Si el token de actualización es válido, actualice el caché derecho de acceso del usuario desde la base de datos y devuelva el nuevo token de acceso y el token de actualización. Si el token de actualización no es válido, devuelva el código de respuesta HTTP 400
  7. Si se devuelven un nuevo token de acceso y un token de actualización, vaya al paso 2. Si se devuelve el código de respuesta HTTP 400, el cliente asume que el token de actualización ha caducado y solicita el nombre de usuario y la contraseña al usuario
  8. Para cerrar sesión, purgue el almacenamiento local

Con este enfoque, estamos haciendo la operación costosa de cargar el caché con detalles de derechos de acceso específicos del usuario cada 30 minutos. Por lo tanto, si se revoca un acceso o se otorga un nuevo acceso, se tarda 30 minutos en reflejarse o se cierra la sesión seguido de un inicio de sesión.

Esa es la forma de hacerlo: Usando OAuth 2.0 para iniciar sesión .

Puede usar otros métodos de autenticación distintos de Google siempre que sea compatible con OAuth.

Para responder a esta pregunta desde mi entendimiento ...

Un sistema de autenticación que utiliza REST para que no necesite realmente rastrear o administrar a los usuarios en su sistema. Esto se hace utilizando los métodos HTTP POST, GET, PUT, DELETE. Tomamos estos 4 métodos y pensamos en ellos en términos de interacción con la base de datos como CREAR, LEER, ACTUALIZAR, ELIMINAR (pero en la web usamos POST y GET porque eso es lo que soportan las etiquetas de anclaje actualmente). Entonces, al tratar POST y GET como CREAR / LEER / ACTUALIZAR / BORRAR (CRUD), podemos diseñar rutas en nuestra aplicación web que podrán deducir qué acción de CRUD estamos logrando.

Por ejemplo, en una aplicación Ruby on Rails podemos construir nuestra aplicación web de modo que si un usuario que ha iniciado sesión visita http://store.com/account/logout , entonces el GET de esa página puede verse como el usuario que intenta cerrar sesión. En nuestro controlador de rieles, construiríamos una acción que desconecte al usuario y lo envíe de vuelta a la página de inicio.

Un OBTENER en la página de inicio de sesión generaría un formulario. una POST en la página de inicio de sesión se vería como un intento de inicio de sesión y tomaría los datos de POST y los usaría para iniciar sesión.

Para mí, es una práctica de usar métodos HTTP asignados a su significado de base de datos y luego construir un sistema de autenticación teniendo en cuenta que no necesita pasar ninguna identificación de sesión o rastrear sesiones.

Todavía estoy aprendiendo; si encuentras algo que he dicho que está mal, corrígeme, y si obtienes más información, publícalo aquí. Gracias.

El uso de una infraestructura de clave pública en la que el registro de una clave implica un enlace adecuado garantiza que la clave pública esté vinculada a la persona a la que está asignada de manera que se garantice el no repudio

Ver http://en.wikipedia.org/wiki/Public_key_infrastructure . Si sigue los estándares adecuados de PKI, la persona o agente que usa la clave robada de manera incorrecta puede ser identificada y bloqueada. Si se requiere que el agente use un certificado, el enlace se vuelve bastante ajustado. Un ladrón inteligente y rápido puede escapar, pero deja más migajas.

Consejos válidos para proteger cualquier aplicación web

Si desea asegurar su aplicación, entonces definitivamente debe comenzar usando HTTPS en lugar de HTTP , esto asegura la creación de un canal seguro entre usted y amp; los usuarios que evitarán rastrear los datos enviados de vuelta & amp; a los usuarios & amp; ayudará a mantener la confidencialidad de los datos intercambiados.

Puede usar JWT (tokens web JSON) para asegurar API RESTful , esto tiene muchos beneficios en comparación con las sesiones del lado del servidor, los beneficios son principalmente:

1- Más escalable, ya que sus servidores API no tendrán que mantener sesiones para cada usuario (lo que puede ser una gran carga cuando tiene muchas sesiones)

2- Los JWT son autocontenidos & amp; tienen los reclamos que definen el rol del usuario, por ejemplo & amp; a qué puede acceder & amp; emitido en la fecha & amp; fecha de vencimiento (después de la cual JWT no será válido)

3- Más fácil de manejar a través de balanceadores de carga y amp; si tiene varios servidores API, ya que no tendrá que compartir datos de sesión ni configurar el servidor para enrutar la sesión al mismo servidor, siempre que una solicitud con un JWT llegue a cualquier servidor, se puede autenticar & amp; autorizado

4- Menos presión en tu DB y no tendrás que almacenar constantemente & amp; recuperar id de sesión & amp; datos para cada solicitud

5- Los JWT no pueden ser manipulados si usa una clave segura para firmar el JWT, por lo que puede confiar en los reclamos en el JWT que se envía con la solicitud sin tener que verificar la sesión del usuario & amp; ya sea que esté autorizado o no, puede verificar el JWT & amp; entonces ya está listo para saber quién & amp; lo que este usuario puede hacer.

Muchas bibliotecas proporcionan formas fáciles de crear & amp; valide los JWT en la mayoría de los lenguajes de programación, por ejemplo: en node.js uno de los más populares es jsonwebtoken

Dado que las API REST generalmente tienen como objetivo mantener el servidor sin estado, los JWT son más compatibles con ese concepto ya que cada solicitud se envía con token de autorización que es autónomo (JWT) sin que el servidor tenga que hacer un seguimiento de la sesión del usuario en comparación con las sesiones que hacen que el servidor tenga estado para que recuerde al usuario & amp; su papel, sin embargo, las sesiones también son ampliamente utilizadas & amp; tienen sus profesionales, que puede buscar si lo desea.

Una cosa importante a tener en cuenta es que debe entregar de forma segura el JWT al cliente utilizando HTTPS & amp; guárdelo en un lugar seguro (por ejemplo, en el almacenamiento local).

Puede obtener más información sobre los JWT desde este enlace

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top