¿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.
¿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.
Respuestas:
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:
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 estándar HTTPS, 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 característica similar a LogOut aquí), algo de consumo de CPU adicional del lado del servidor, 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 la autenticación implícita , pero también requiere HTTPS, ya que es vulnerable a ataques MiM o Replay , 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 los ataques MiM o Replay .
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. Vea 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 es apátrida, depende de los detalles de transmisión de HTTP y está sujeto a muchas debilidades de seguridad , incluidos MiM y Replay, por lo que debe usarse solo sobre HTTPS. Por lo general, 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. Ver este artículo de referencia .
Se definió como tal en este artículo:
Todas las consultas REST deben autenticarse firmando los parámetros de consulta ordenados en orden alfabético en minúsculas utilizando la credencial privada como token de firma. La firma debe ocurrir antes de que la URL codifique la cadena de consulta.
Esta técnica es quizás la más compatible con una arquitectura sin estado, y también se puede implementar con una administración de sesión ligera (usando sesiones en memoria en lugar de persistencia DB).
Por ejemplo, aquí hay una muestra genérica de URI del enlace de arriba:
GET /object?apiKey=Qwerty2010
debe transmitirse como tal:
GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789
La cadena que se firma es /object?apikey=Qwerty2010×tamp=1261496500
y la firma es el hash SHA256 de esa cadena usando el componente privado de la clave API.
El almacenamiento en caché de datos del lado del servidor puede estar siempre disponible. Por ejemplo, en nuestro marco, almacenamos en caché las respuestas a nivel de SQL, no a nivel de URI. Por lo tanto, agregar este parámetro adicional no rompe el mecanismo de caché.
Consulte este artículo para obtener algunos detalles sobre la autenticación RESTful en nuestro marco ORM / SOA / MVC cliente-servidor, basado en JSON y REST. Dado que permitimos la comunicación no solo a través de HTTP / 1.1, sino también canalizaciones con nombre o mensajes GDI (localmente), intentamos implementar un patrón de autenticación verdaderamente RESTful, y no confiar en la especificidad HTTP (como encabezado o cookies).
Nota posterior : agregar una firma en el URI puede verse como una mala práctica (ya que, por ejemplo, aparecerá en los registros del servidor http), por lo que debe mitigarse, por ejemplo, mediante un TTL adecuado para evitar repeticiones. Pero si sus registros http están comprometidos, seguramente tendrá mayores problemas de seguridad.
En la práctica, la próxima autenticación de tokens MAC para OAuth 2.0 puede ser una gran mejora con respecto al esquema actual "Concedido por token". Pero esto sigue siendo un trabajo en progreso y está vinculado a la transmisión HTTP.
Conclusión
Vale la pena concluir que REST no solo se basa en HTTP, incluso si, en la práctica, también se implementa principalmente a través de HTTP. REST puede usar otras capas de comunicación. Por lo tanto, una autenticación RESTful no es solo un sinónimo de autenticación HTTP, sea lo que sea que Google responda. Incluso no debe usar el mecanismo HTTP en absoluto, sino que debe abstraerse de la capa de comunicación. Y si usa la comunicación HTTP, gracias a la iniciativa Let's Encrypt no hay razón para no usar HTTPS adecuado, que se requiere además de cualquier esquema de autenticación.
Cookie
como un mejor reemplazo HTTP Basic Auth
, puede realizar una autenticación verdaderamente sin estado con un método para expirar la autenticación y la capacidad de cerrar sesión. Una implementación de ejemplo podría usar una cookie llamada Emulated-HTTP-Basic-Auth
con un valor similar a la autenticación básica HTTP real y además establecer el tiempo de caducidad. El cierre de sesión se puede implementar eliminando esa cookie. Supongo que cualquier cliente capaz de admitir HTTP Basic Auth también puede admitir la autenticación de cookies de esta manera.
Cookie
lugar, se puede usar una emulación proporcionada por el servidor para las mismas cosas en otro encabezado ( ).
Dudo si las personas que gritaban con entusiasmo "Autenticación HTTP" alguna vez intentaron hacer 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 alguna vez 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:
Aquí hay un artículo muy perspicaz que aborda estos puntos por punto , pero esto resulta en una gran cantidad 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 se usan las cookies 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 información del lado del cliente se envía al servidor en cada solicitud, de nuevo al igual que la información de autenticación HTTP. Conceptualmente, la única diferencia es que el servidor puede determinar el contenido de esta parte del estado del lado del cliente como parte de su respuesta.
Al hacer que las sesiones sean un recurso RESTful con solo las siguientes reglas:
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 establecida 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 que no son RESTful usan esencialmente lo 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 se podría usar un lenguaje de aceptación para acceder a los recursos de traducción, etc. Siento que es lo mismo, pero tal vez otros no. ¿Qué piensan 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:
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, "basadas en el navegador" como señala Skrebbel 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 hace a las API REST de back-end.
Considere esto: tiene una plataforma de datos / información expuesta como activo 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. Por lo tanto, 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:
Camino-1:
Camino-2:
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, otras API de REST de su catálogo deben confiar en esa "clave de valet".
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 yo divago.
El punto es que se debe mantener y compartir un "estado" (sobre el estado autenticado del cliente) 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 cualquiera / 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 coincidencias hash (el estilo AWS). Y arquitectónicamente, cada API REST necesitará realizar esto, sospecho, usando un servicio de inicio de sesión común. Porque, si no lo hace, entonces ensucia el código de autenticación en todas partes. Un gran desastre.
Entonces más capas, más latencia.
Ahora, tome Way-1 y aplique a HTM. ¿A su usuario (humano) realmente le importa si tiene que enviar uid / pwd / hash o lo que sea con cada solicitud? No, siempre y cuando no la molestes lanzando la página de autenticación / inicio de sesión cada segundo. Buena suerte teniendo clientes si lo haces. Entonces, lo que hará es almacenar la información de inicio de sesión en algún lugar del lado del cliente, en el navegador, justo al principio, y enviarla con cada solicitud realizada. Para el usuario (humano), ella ya inició sesión y hay una "sesión" disponible. Pero en realidad, ella se autentica en cada solicitud.
Lo mismo con Way-2. Su usuario (humano) nunca se dará cuenta. Entonces no se hizo daño.
¿Qué pasa si aplicamos Way-1 a MTM? En este caso, dado que es una máquina, podemos aburrir a este tipo pidiéndole que envíe información de autenticación con cada solicitud. ¡A nadie le importa! Realizar Way-2 en MTM no provocará ninguna reacción especial; Es una maldita máquina. ¡Podría importarle menos!
Entonces, realmente, la pregunta es qué se adapta a sus necesidades. La apatridia tiene un precio que pagar. Paga el precio y sigue adelante. Si quieres ser purista, paga el precio por eso también y sigue adelante.
Al final, las filosofías no importan. Lo que realmente importa es el descubrimiento de información, la presentación y la experiencia de consumo. Si la gente ama tus API, hiciste tu trabajo.
Way-3
, el enfoque híbrido. El cliente inicia sesión como en Way-2
pero, como en Way-1
, las credenciales no se verifican en ningún estado del lado del servidor. En cualquier caso, se crea un token de autenticación y se devuelve al cliente como en Way-2
. Posteriormente se verifica la autenticidad de este token utilizando criptografía asimétrica sin buscar ningún estado específico del cliente.
Aquí hay una solución de autenticación verdaderamente y completamente RESTful:
Cuando un cliente se autentica:
3.1. emitir un token que contenga lo siguiente:
3.2. Cifre el token con la clave privada.
3.3. Envíe el token cifrado al usuario.
Cuando el usuario accede a cualquier API, también debe pasar su token 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 podría 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 obtener la contraseña del usuario y almacenarla del 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 abrazar OO puro y si algo no es un objeto, entonces lo estás haciendo mal. Dáme un respiro.
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) hasta el 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, ¿cuál es el problema?
Estoy abierto a aceptar correcciones en los comentarios, pero simplemente 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 INALÁMBRICO (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.
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 es autodescriptiva 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 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.
El enfoque mencionado anteriormente a continuación es esencialmente el tipo de concesión "Credencial de contraseña del propietario del recurso" 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 el tipo de concesión "Código de autorizació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 del 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:
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.
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 al individuo al que está asignada de una manera que 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 veloz puede escapar, pero deja más migajas.
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 de 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 de Ruby on Rails podemos construir nuestra aplicación web de manera que si un usuario que ha iniciado sesión visita http://store.com/account/logout , 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 regreso a la página de inicio.
Un GET 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.
Consejos válidos para asegurar cualquier aplicación web
Si desea proteger 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 los usuarios que evitará rastrear los datos enviados de un lado a otro a los usuarios y ayudará a mantener los datos Intercambio confidencial.
Puede usar JWT (JSON Web Tokens) para proteger las 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 independientes y tienen los reclamos que definen el rol del usuario, por ejemplo, y a qué puede acceder y emitido en la fecha y fecha de vencimiento (después de lo cual JWT no será válido)
3- Más fácil de manejar a través de equilibradores de carga y si tiene múltiples 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 y autorizado
4- Menos presión en su base de datos y no tendrá que almacenar y recuperar constantemente la identificación y los datos de la sesión 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 y si está autorizado o no , solo puede verificar el JWT y luego estará listo para saber quién y qué puede hacer este usuario.
Muchas bibliotecas proporcionan formas fáciles de crear y validar 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 realizar un seguimiento de la sesión del usuario en comparación con las sesiones que hacen que el servidor servidor con estado para que recuerde al usuario y su función, sin embargo, las sesiones también se usan ampliamente y tienen sus ventajas, 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 y guardarlo en un lugar seguro (por ejemplo, en el almacenamiento local).
Puede obtener más información sobre los JWT en este enlace