Autenticación RESTful

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

    Cómo manejar la autenticación en una architecture RESTful Cliente-Servidor es una cuestión de debate.

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

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

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

    Cada esquema de autenticación tiene sus propias PRO y CONs, según el propósito de su política de seguridad y architecture de software.

    Autorización básica de 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 espantosa ventana de autenticación que se muestra en el navegador, que persistirá (no hay una característica similar a LogOut), alguna CPU adicional del lado del servidor consumo, y el hecho de que el nombre de usuario y la contraseña se transmiten (a través de HTTPS) al Servidor (debe ser más seguro dejar la contraseña solo en el lado del cliente, durante la entrada del teclado, y almacenarse como hash seguro en el Servidor).

    Podemos usar Autenticación implícita , pero también requiere HTTPS, ya que es vulnerable a los ataques MiM o Reproducción , y es específico de HTTP.

    Sesión a través de cookies

    Para ser sincero, una sesión administrada en el servidor no es verdaderamente apátrida.

    Una posibilidad podría ser mantener todos los datos dentro del contenido de la cookie. Y, por diseño, la cookie se maneja en el lado del servidor (de hecho, el cliente ni siquiera intenta interpretar esta información de cookies: simplemente 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 administrarlo, 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í misma 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 mediante 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. Ver 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 la transmisión HTTP y está sujeto a una gran cantidad de debilidades de seguridad , incluidos MiM y Replay, por lo que debe usarse solo a través de HTTPS.

    Autenticación de consultas

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

    Fue definido como tal en este artículo:

    Todas las consultas REST deben autenticarse firmando los parámetros de consulta ordenados en minúsculas, orden alfabético con la credencial privada como el 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 architecture sin estado, y también se puede implementar con una gestión de sesión ligera (usando sesiones en memoria en lugar de persistencia de 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 está firmando es /object?apikey=Qwerty2010&timestamp=1261496500 y la firma es el hash SHA256 de esa cadena que usa el componente privado de la clave API.

    El almacenamiento en caché de datos del lado del servidor siempre puede estar disponible. Por ejemplo, en nuestro marco, almacenamos en caché las respuestas en el nivel SQL, no en el nivel 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 cliente / servidor ORM / SOA / MVC, 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 de HTTP (como el encabezado o las cookies).

    En la práctica, la próxima Autenticación de Token MAC para OAuth 2.0 puede ser una gran mejora con respecto al esquema actual “Concedido por Token”. Pero esto todavía es un trabajo en progreso y está vinculado a la transmisión HTTP.

    Conclusión

    Vale la pena concluir que REST no solo está basado en HTTP, incluso si, en la práctica, 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, independientemente de las respuestas de Google. Incluso no debería usar el mecanismo HTTP en absoluto, sino que debe abstraerse de la capa de comunicación.

    Dudo que la gente que gritó con entusiasmo “Autenticación HTTP” alguna vez intentó 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é con el uso de Autenticación HTTP en los servicios RESTful que producen páginas HTML para ser vistos en un navegador son:

    • el usuario generalmente recibe un feo cuadro de inicio de sesión hecho por el navegador, que es muy poco amigable para el usuario. no puede agregar recuperación de contraseña, cuadros de ayuda, etcétera.
    • cerrar la 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 está aquí , pero esto da como resultado una gran cantidad de hackeos de JavaScript específicos del navegador, soluciones para soluciones temporales, etcétera. Como tal, tampoco es compatible con versiones anteriores, por lo que requerirá mantenimiento constante a medida que se lanzan 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 cookies son malas, ¿verdad? No, no lo son, la forma en que se utilizan a menudo las cookies es malvada. 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 de la que el navegador realizaría un seguimiento mientras navegas. Y esta información del lado del cliente se envía al servidor cada vez que se solicita, igual que la información de autenticación HTTP. Conceptualmente, la única diferencia es que el contenido de esta parte del estado del cliente puede ser determinado por el servidor como parte de su respuesta.

    Haciendo de las sesiones un recurso RESTful con solo las siguientes reglas:

    • Una sesión mapea una clave para 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.
    • El inicio de sesión significa POSTING en / sessions, una nueva clave se configura como una cookie
    • Cerrar sesión significa DELETEing / sessions / {key} (con POST sobrecargado, recuerde, somos un navegador, y HTML 5 está aún 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 es que el servidor genera la clave de autenticación y la envía al cliente que la sigue enviando, en lugar de que el cliente la compute a partir de las credenciales ingresadas.

    converter42 agrega que al usar https (que deberíamos), es importante que la cookie tenga su bandera segura 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.

    Siento que esta es una solución suficiente que funciona bien, pero debo admitir que no soy lo suficientemente experto en seguridad para identificar agujeros potenciales en este esquema; todo lo que sé es que cientos de aplicaciones web no RESTful usan esencialmente lo mismo protocolo de inicio de sesión ($ _SESSION inphp, HttpSession en Java EE, etc.). El contenido del encabezado de la cookie se usa simplemente para direccionar un recurso del lado del servidor, al igual que un idioma de aceptación podría usarse para acceder a los recursos de traducción, etcétera. Siento que es lo mismo, ¿pero quizás otros no? ¿Qué piensan chicos?

    Bastante ya se dice sobre este tema aquí. Pero aquí está mi 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 los humanos o las máquinas.

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

    Cuando consideramos esto en el contexto de las aplicaciones de humano a máquina, “basadas en navegador” como señala Skrebbel más arriba, esto significa que la aplicación (web) que se ejecuta en el navegador deberá enviar su estado e información relevante con cada solicitud hace a la parte trasera API REST.

    Considere esto: tiene una plataforma de datos / información expuesta como un conjunto de 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) la aplicación web, (2) la aplicación móvil y (3) alguna aplicación de terceros. Al final, incluso la cadena de MTM conduce a HTM, a la derecha. Entonces los usuarios humanos permanecen en el vértice de la cadena de información.

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

    El concepto de autenticación se aplica en todos los ámbitos. ¿Cómo se diseñará esto para que se acceda a sus API REST de manera uniforme y segura? La forma en que veo esto, hay 2 formas:

    Way-1:

    1. No hay inicio de sesión para comenzar. Cada solicitud realiza el inicio de sesión
    2. El cliente envía sus parámetros de identificación + los parámetros específicos de la solicitud con cada solicitud
    3. La API REST los toma, da la vuelta, hace ping a la tienda del usuario (lo que sea que sea) y confirma la autenticación
    4. Si se establece la autenticación, los servicios de la solicitud; de lo contrario, niega con el código de estado HTTP apropiado
    5. Repite lo anterior para cada solicitud en todas las API REST de tu 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 las solicitudes
    3. Toma los parámetros de autenticación (clave de API, uid / pwd o lo que usted elija) y verifica la autenticación contra el almacén de usuarios (LDAP, AD o MySQL DB, etc.)
    4. Si se verifica, crea un token de autenticación y se lo devuelve al cliente / llamante
    5. La persona que llama luego envía este token de autenticación + parámetros específicos de solicitud con cada solicitud posterior a otras API de REST de negocios, hasta que se cierra la sesión o hasta que vence el contrato

    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, es necesario que otras API de REST de su catálogo confíen 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 repository compartido y confiable de tokens puede ser local / federado, permitiendo 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 todas las solicitudes que ingresen.

    Realizar la autenticación es un proceso intensivo de recursos. Imagínese la ejecución de consultas SQL, para cada solicitud entrante, contra su tienda de usuario para verificar la coincidencia uid / pwd. O, para encriptar y realizar coincidencias hash (el estilo AWS). Y desde el punto de vista arquitectónico, todas las API REST necesitarán realizar esto, sospecho, utilizando un servicio común de inicio de sesión. Porque, si no lo haces, entonces tiras el código de autenticación en todas partes. Un gran desastre.

    Así que 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 pedido? No, siempre y cuando no la molestes lanzando la página de autenticación / inicio de sesión cada segundo. Buena suerte tener clientes si lo hace. Por lo tanto, lo que hará es almacenar la información de inicio de sesión en algún lugar en el lado del cliente, en el navegador, al principio, y enviarla con cada solicitud realizada. Para el usuario (humano), ella ya ha iniciado sesión, y hay una “sesión” disponible. Pero, en realidad, ella está autenticada en cada solicitud.

    Lo mismo con Way-2. Su usuario (humano) nunca lo notará. Entonces no hay daño hecho.

    ¿Qué pasa si aplicamos Way-1 a MTM? En este caso, dado que es una máquina, podemos aburrir muchísimo a este tipo al pedirle 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. ¡No podría importarle menos!

    Entonces, realmente, la pregunta es qué satisface tu necesidad. Apatridia tiene un precio a pagar. Pague el precio y siga adelante. Si quieres ser un purista, entonces paga el precio por eso 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.

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

    1. Cree un par de claves públicas / privadas 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 expiración
      • nombre de los usuarios (opcional)
      • IP de los usuarios (opcional)
      • hash de una contraseña (opcional)

      3.2. Encripta el token con la clave privada.

      3.3. Envíe el token encriptado nuevamente 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 mediante la clave pública del servidor de autenticación.

    Esta es la 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 encriptada junto con el token de autenticación. El servidor podría verificar que la contraseña coincida con la contraseña que se utilizó para crear el token de autenticación mediante la comparación de hashes. Una conexión segura usando algo como HTTPS sería necesaria. 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 cifrada 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 apátridas 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 te facilita la vida y reduce los gastos generales y el costo de las sesiones, trata de seguirlo como es una buena idea, pero en el momento en que sigas una disciplina (cualquier disciplina / guía) hasta el extremo donde ya no brinda el beneficio para el que estaba destinado, entonces lo estás haciendo mal. Algunos de los mejores lenguajes de hoy tienen tanto progtwigción funcional como 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 en el encabezado HTTP, entonces hágalo, simplemente no abuse de ella. Recuerde que las sesiones son malas cuando se vuelven pesadas y grandes, si toda la sesión consiste en una cadena corta que contiene una tecla, entonces, ¿cuál es el problema?

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

    Lo primero y más importante es que 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 involucradas. La forma de realizar la autenticación o autorización en el servicio RESTful es mediante el uso del encabezado Autorización HTTP como se define en las especificaciones HTTP RFC 2616. Cada solicitud debe contener el encabezado Autorización HTTP, y la solicitud debe enviarse a través de una conexión HTTP (SSL). Esta es la forma correcta de realizar la autenticación y verificar la autorización de las solicitudes en un servicio web HTTP RESTful. Implementé un servicio web RESTful para la aplicación Cisco PRIME Performance Manager en Cisco Systems. Y como parte de ese servicio web, también implementé autenticación / autorización.

    Rubens Gomes.

    Ciertamente no se trata de “claves de sesión”, ya que generalmente se utiliza 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í misma sin ningún estado de aplicación del lado del servidor.

    La manera más fácil de abordar esto es comenzando con los mecanismos de autenticación incorporados 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 enrevesado pero realmente roto.

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

    (Lo siento, no puedo comentar sobre la respuesta).

    Yo diría que el RESTO y la autenticación simplemente no se mezclan. REST significa sin estado pero ‘autentificado’ es un estado. No puedes tenerlos a ambos en la misma capa. Si usted es un defensor RESTful y frunce el ceño ante los estados, entonces debe ir con HTTPS (es decir, deje el problema de seguridad en otra capa).

    I think restful authentication involves the passing of an authentication token as a parameter in the request. Examples are the use of apikeys by api’s. I don’t believe the use of cookies or http auth qualifies.

    I think the following approach can be used for REST service authentication:

    1. Create a login RESTful API to accept username and password for authentication. Use HTTP POST method to prevent caching and SSL for security during transit On successful authentication, the API returns two JWTs – one access token (shorter validity, say 30 minutes) and one refresh token (longer validity, say 24 hours)
    2. The client (a web based UI) stores the JWTs in local storage and in every subsequent API call passes the access token in “Authorization: Bearer #access token” header
    3. The API checks the validity of the token by verifying the signature and expiry date. If the token is valid, check if the user (It interprets the “sub” claim in JWT as username) has access to the API with a cache lookup. If the user is authorized to access the API, execute the business logic
    4. If the token is expired, the API returns HTTP response code 400
    5. The client, on receiving 400/401, invokes another REST API with the refresh token in “Authorization: Bearer #refresh token” header to get a new access token.
    6. On receiving the call with refresh token, check if the refresh token is valid by checking the signature and the expiry date. If the refresh token is valid, refresh the access right cache of the user from DB and return new access token and refresh token. If the refresh token is invalid, return HTTP response code 400
    7. If a new access token and refresh token are returned, go to step 2. If HTTP response code 400 is returned, the client assumes that the refresh token has expired and asks for username and password from the user
    8. For logout, purge the local storage

    With this approach we are doing the expensive operation of loading the cache with user specific access right details every 30 minutes. So if an access is revoked or new access is granted, it takes 30 minutes to reflect or a logout followed by a login.

    That’s the way to do that: Using OAuth 2.0 for Login .

    You may use other authentication methods other then Google’s as long as it supports OAuth.

    To answer this question from my understanding…

    An authentication system that uses REST so that you do not need to actually track or manage the users in your system. This is done by using the HTTP methods POST, GET, PUT, DELETE. We take these 4 methods and think of them in terms of database interaction as CREATE, READ, UPDATE, DELETE (but on the web we use POST and GET because that is what anchor tags support currently). So treating POST and GET as our CREATE/READ/UPDATE/DELETE (CRUD) then we can design routes in our web application that will be able to deduce what action of CRUD we are achieving.

    For example, in a Ruby on Rails application we can build our web app such that if a user who is logged in visits http://store.com/account/logout then the GET of that page can viewed as the user attempting to logout. In our rails controller we would build an action in that logs the user out and sends them back to the home page.

    A GET on the login page would yield a form. a POST on the login page would be viewed as a login attempt and take the POST data and use it to login.

    To me, it is a practice of using HTTP methods mapped to their database meaning and then building an authentication system with that in mind you do not need to pass around any session id’s or track sessions.

    I’m still learning — if you find anything I have said to be wrong please correct me, and if you learn more post it back here. Gracias.

    Using a Public key infrastruction in which the registration of a key involves proper binding ensures that the public key is bound to the individual to which it is assigned in a way that ensures non-repudiation

    See http://en.wikipedia.org/wiki/Public_key_infrastructure . If you follow the proper PKI standards, the person or agent who improperly uses the stolen key can be identified and locked out. If the agent is required to use a certificate, the binding gets pretty tight. A clever and quick-moving thief can escape, but they leave more crumbs.