OAuth 2.0: equilibrio y usabilidad en la securización de APIs

En los últimos años, con el auge del uso de las APIs y el interés por parte de las empresas en incorporar plataformas API Management dentro del concepto del API Economy en sus organizaciones, surge la necesidad de securizar las APIs.

La estrategia de securización de APIs debe encontrar el equilibrio entre la seguridad y la usabilidad. Una estrategia demasiado compleja disuade a usuarios malintencionados, pero también obstaculiza su uso por parte de usuarios legítimos.

El uso de estándares ayuda a conseguir ese equilibrio, ya que son suficientemente complejos como para disuadir a usuarios maliciosos y, proporcionando la información correcta, permiten el acceso a usuarios autorizados.

Cualquiera que sea la decisión respecto a la seguridad de las APIs en una organización, se debe poner foco en los siguientes aspectos:

  • Autenticar a los consumidores de las APIs y establecer el nivel de confianza asociado a cada uno de ellos.
  • Solicitar la autorización explícita de los consumidores para la ejecución de ciertas tareas.
  • Disponer de herramientas que rastreen las peticiones de forma end-to-end que permitan identificar todas las partes involucradas en el flujo y garantizar la responsabilidad de cada una de ellas.

No solo el acceso a las APIs necesita control, también encontramos el inconveniente del intercambio de contraseñas. Surge, además, el problema de la delegación de la autorización para acceder a los datos.

OAuth es un estándar que surge como respuesta a esas necesidades. Es un framework de autorización que se ha convertido en el estándar de facto en el uso de APIs. Permite a las aplicaciones un acceso limitado (scopes) a los datos de los usuarios, sin tener que proporcionar las credenciales de dicho usuario, desacoplando la autenticación y la autorización a los datos.

Da soporte a diferentes escenarios de negocio dependiendo del tipo de consumidor que accede a los datos que expone la API: aplicaciones servidor, navegadores, dispositivos IOT, aplicaciones móviles o nativas, etc.

De una manera simplificada, el uso de OAuth es análogo al uso de una tarjeta de acceso a un hotel.

Para obtener la tarjeta de acceso, el primer paso es pasar un proceso de autenticación tras el cual te dan la tarjeta (un access token), posteriormente puedes usar la tarjeta para acceder a los distintos partes del hotel (recursos de la API) a las cuales se tiene permiso para acceder o no dependiendo de la autenticación.

¿Qué es y qué no es OAuth 2.0?

Autenticación vs autorización

Con frecuencia, cuando se habla de seguridad y de OAuth, los conceptos de autenticación y autorización se solapan y son completamente diferentes:

  • La autenticación se define como el proceso mediante el cual se verifica quién eres, es decir, su ámbito se refiere a la identificación.
  • La autorización es el proceso mediante el cual se verifica a qué tienes acceso, es decir, su ámbito se limita al control de acceso.

Atendiendo a esos conceptos, OAuth es un framework que permite delegar la autorización de acceso a las APIs, NO es un protocolo de autenticación. Este matiz incluso lo informan en su documentación.

En todo el proceso de uso de este framework no se indica nada sobre la autenticación del cliente, ni información relacionada con él, sólo se habla de la obtención de un token para acceder a un recurso.

Normalmente, en el proceso de autenticación de un usuario hay información de quién es ese usuario, cuándo se autentico y cómo se realizó este proceso de autenticación. Toda esta información no es accesible ni gestionable mediante OAuth, no hay información “útil” del usuario ya que los tokens son opacos y no contienen información sobre la identidad del usuario.

Hay que destacar que importantes empresas como son Facebook y Twitter emplean OAuth, no solo para la autorización, sino como pseudoautenticación habilitando un recurso/me que mediante un token de acceso ofrece información básica de dicho usuario.

Pero también hay que recalcar que en todo el estándar no se requiere la implementación de este recurso en absoluto.

¿Qué diferencia OAuth de JWT?

Lo más importante es comprender que ni son comparables ni son excluyentes:

  • JWT es un protocolo de autenticación basado en un estándar abierto (RFC 7519), que define el conjunto de operaciones para emitir y validar tokens firmados. El estándar define la estructura interna que contiene el token.
    La información incluida dentro de este token es un formato JSON y el método de firmado puede variar desde un algoritmo HMAC a un par de claves públicas/privadas de RSA.
  • OAuth es un framework de autorización, que proporciona una guía en la que definen los flujos de autorización específicos para acceder a los datos del usuario desde diferentes tipos de aplicaciones consumidoras. En OAuth se utilizan diferentes tipos de tokens entre ellos el propio token JWT.

¿Qué relación tiene OAuth con OpenId Connect?

OpenId es un es un estándar abierto que permite autenticar usuarios mediante peticiones HTTP en formato JSON.

OpenId Connect es un protocolo de autenticación de usuarios que se basa en OpenId y extiende OAuth 2.0 dotándolo de una capa de autenticación de usuarios sin que estos últimos tengan que almacenar y gestionar las contraseñas.

Su framework estandariza la comunicación entre un proveedor de identidades (IDPs) de OpenId y un tercero. Su funcionamiento es muy sencillo: un usuario obtiene una cuenta a través de un proveedor de identidades de OpenID, por ejemplo Google, y el usuario puede usar esa cuenta para acceder a cualquier web (tercero) que acepte la autenticación OpenId, por ejemplo Youtube sería un tercero que acepta la cuenta de Google como login.

Entonces, ¿siempre hay que usar OAuth en el mundo de las APIs?

No siempre, es el método más extendido y el recomendado para la mayoría de casuísticas, pero existen otros métodos de seguridad que son más apropiados en ciertos escenarios de negocio siguiendo el concepto de equilibrio de usabilidad y seguridad que se comentaba al principio.

¿Qué protocolos hay que utilizar?

API Keys

Una API Key es una pieza de código, normalmente una cadena larga de caracteres, que se asigna a un consumidor de una API cuyo valor es único y es utilizada por parte de ese consumidor en cada una de las solicitudes a la API.

Normalmente, en el momento en que un consumidor se registra se generan estas claves que le permiten operar de un modo similar al uso de un usuario y una contraseña de acceso.

Debido a que el valor de una API Key es único, es frecuente utilizar estas claves como método de autenticación de los usuarios.

La ventajas del uso de este tipo de claves son:

  • La sencillez de su uso.
  • La autonomía, ya que la clave es independiente del servidor de nombres y credenciales.

Pero este método también tiene sus desventajas y es el menos seguro de los que se recomiendan debido a:

  • La delegación de la responsabilidad del almacenamiento de la clave, ya que en la mayoría de las implementaciones la seguridad del sistema reside en la capacidad del consumidor para proteger sus claves y el uso correcto de la misma: que cifre el tráfico, que proteja su red, que no compartan la clave entre diferentes servicios con distinto propósito, que no ponga las claves en su código, etc.
  • La falta del control granular, es decir, no hay manera de limitar el acceso a ciertos recursos o APIs mediante esta API Key.
  • La clave no caduca con el tiempo. Sería posible implementar algún sistema de rotado de claves que minimice este problema, pero es algo bastante complejo.
  • El uso incorrecto por la falta de comprensión del propósito de esta clave. Esta clave por naturaleza no es una solución completa de seguridad, fue pensada como método de identificación, no como un método seguro de autenticación y autorización.

Los casos de uso donde este método sería una opción a considerar son aquellos con comunicaciones de tipo servidor-servidor alojados dentro de infraestructura de la propia organización y si es posible solo para funcionalidades consultivas.

OAuth 2.0

Como se ha explicado previamente OAuth 2.0 es un framework de autorización que permite controlar el acceso por parte de las aplicaciones a los datos de los usuarios sin tener que proporcionar las credenciales.

Como ventajas del uso de este framework se pueden citar:

  • Es un protocolo muy flexible que se basa en SSL (Secure Sockets Layer) que cifra las conexiones y permite manejar el access token de forma segura.
  • El acceso es limitado, tanto en tiempo porque los tokens caducan, como en funcionalidad gracias a los scopes.
  • Permite compartir datos sin tener que revelar información personal.
  • Existen multitud de herramientas y SDKs que permiten su uso por parte de los desarrolladores.

Es la opción de securización de APIs por defecto en la mayoría de los casos. Es necesario definir en función de la aplicación y datos expuestos qué tipo de flujo de autorización es necesario para proporcionar el token de acceso a los datos por parte de la aplicación.

OpenId Connect

Como se explicó previamente, OpenID Connect es una extensión de OAuth por lo que  tiene todas las ventajas citadas anteriormente.

Las ventajas principales de su uso son:

  • Permitir a las aplicaciones autenticar usuarios sin tener que almacenar y administrar contraseñas.
  • Permitir administrar su propia instancia OAuth que permita el acceso a los recursos
  • Usar un proveedor de identidades externo para autenticar a los usuarios como Google.

El principal caso de uso de este tipo de seguridad es proporcionar a los usuarios la posibilidad de autenticarse a través de diferentes(proveedores de identidades (IDPs).

¿Qué método elijo: API Key, OAuth 2.0 u OpenId Connect?

¿Qué no hay que utilizar para securizar nuestras APIs?

  • OAuth 1.0: la versión 2.0 introdujo como mejoras la inclusión de múltiples dispositivos (browsers, nativos, servidores, etc) y sobre todo se sustituyó la firma de las peticiones por TLS.
  • Certificados SSL: solo gestionan la autenticación y son complejos de usar por los clientes.
  • Autenticación básica: solo autentica, no gestiona la autorización y las credenciales incluida la contraseña son fácilmente obtenibles.
  • SAML: no es posible delegar la autorización a un tercero, no hay registro dinámico ni dispone de estructura estándar de identificación.
  • Métodos customizados: no es necesario reinventar la rueda, AOauth es un estándar suficientemente testado y confiable como para usarse, además los desarrolladores ya están habituados a su uso.

¿Cuáles son los flujos de OAuth y cuándo los uso?

Conceptos: scopes, tokens y actores

El primer paso para comprender los flujos de OAuth y los escenarios de aplicación de cada uno de ellos es comprender algunos conceptos previos como son: los actores que intervienen en los flujos, qué son los tokens y los scopes de acceso.

Los actores que intervienen en todos los flujos OAuth son:

Los scopes son una lista de identificadores separados por espacios que se utilizan en el proceso de autorización y consentimiento de las APIs en los tokens OAuth, que permiten determinar a qué se solicita acceso por parte de la aplicación y a qué se autoriza acceder por parte del usuario. Por ejemplo: a las fotos, mensajes de usuarios. etc,

Los tokens e identificadores que se manejan dentro de OAuth son:

  • El client id es un identificador único que representa la aplicación en el servidor de autenticación.
  • El client secret es una clave secreta que pertenece a la aplicación que es utilizada por el servidor de autorización para comprobar si dicha aplicación está autorizada.
  • Los access token: son claves proporcionadas por el servidor de autorización a la aplicación que permite el acceso a las APIs durante un tiempo limitado tras el cual el token deja de ser válido.
  • Los refresh token: es una clave también proporcionada por el servidor de autorización a la aplicación que permite solicitar nuevos access token después de que estos hayan caducado.

Flujos o grant types

Los flujos de OAuth también denominados grant types hacen referencia al modo en que una aplicación obtiene un access token que le permite acceder a los datos expuestos a través de una API.

La existencia de estos flujos por parte del estándar surge para dar respuesta a todos los escenarios de negocio que se pueden presentar en el consumo de las APIs atendiendo a tres variables:

  • El tipo de aplicación consumidora.
  • Su grado de confianza.
  • Cómo es la interactuación por parte del usuario en el proceso.

Client credentials grant type

Este flujo representa el caso en el que la aplicación pertenece al usuario, por lo que no hay necesidad de que éste se autentique ni ayude de forma alguna al servidor de autenticación a decidir si el acceso para esa aplicación está garantizado, es decir, el access token que envía el servidor se obtiene autenticando sólo a la aplicación, no al usuario.

La principal diferencia con el resto del flujos es que el usuario no interactúa en el proceso, por lo que la aplicación no puede actuar en nombre del usuario, solo en nombre propio.

¿Cómo funciona?

  1. La aplicación envía sus credenciales al servidor de autenticación.
  2. El servidor de autenticación comprueba que los datos enviados por la aplicación en la solicitud pertenecen a la aplicación del usuario y, en caso de ser así, le remite el access token.

El siguiente es un diagrama simplificado del flujo Client Credentials y debajo, en este caso idéntico, el diagrama de la documentación de OAuth.

¿Cuándo se utiliza?

  • Tipo de aplicación consumidora: aplicaciones internas de la organización o los datos que expone la API no son sensibles.
  • Interactuación por parte del usuario: ninguna.
  • Grado de confianza de la aplicación: elevado, suele ser interno o los datos que expone la API no son sensibles.
  • Tipo de comunicación: servidor-servidor.

Resource Owner Password grant type

Este flujo se caracteriza por la intervención por parte del usuario proporcionando su usuario y contraseña en la aplicación cliente, no en el servidor de autenticación. Esta situación implica que los dueños del recurso deben confiar plenamente en la aplicación para introducir sus credenciales.

Por ejemplo, en Spotify te solicitan para iniciar sesión las credenciales de Facebook directamente en su aplicación. Si no fuera una aplicación confiable los usuario no pondrían sus datos. Spotify es suficientemente confiable y garantiza que ni guarda ni modifica la contraseña de Facebook.

Pero, ¿no se supone que el hecho de proporcionar las contraseñas era lo que OAuth pretendía evitar? Cierto, pero el uso de este flujo aprovecha el resto de beneficios de OAuth como son el uso de access tokens con una vida útil limitada.

Por ejemplo, si tenemos una aplicación móvil en lugar de almacenar el usuario y contraseña del usuario, la aplicación solicita los datos en el momento de la instalación, de forma posterior solo tiene que hacer uso del access token.

¿Cómo funciona?

  • 1 y 2. Debido a que la aplicación es de confianza el usuario proporciona sus credenciales directamente sobre la aplicación, de esta forma el usuario delega a la aplicación el poder autenticarse contra el servidor posteriormente de manera directa.
  • 3. La aplicación actúa como si fuese el usuario con sus credenciales y se autentica contra el servidor.
  • 4. El servidor de autenticación proporciona el access token y el refresh token si aplica.

El siguiente es un diagrama simplificado del flujo Resource Owner Password Credentials, el diagrama de la documentación de OAuth.

¿Cuándo se utiliza?

  • Tipo de aplicación consumidora: aplicaciones móviles o de escritorio, aplicaciones web alojadas en el servidor o alojadas en cliente si son confiables y no una third party.
  • Grado de confianza de la aplicación: un tercero confiable.
  • Interactuación por parte del usuario: consentimiento mediante usuario y contraseña.
  • Tipo de comunicación: se utiliza habitualmente en comunicaciones cliente-servidor.

Authorization code grant type

Este flujo se caracteriza por la intervención del usuario para autorizar de forma explícita el acceso a sus datos por parte de la aplicación y por el uso de un código proporcionado por el servidor de autenticación para que la aplicación pueda obtener un access token.

¿Cómo funciona?

  1. La aplicación solicita al usuario el consentimiento expreso para acceder a los datos abriendo un navegador al usuario donde explicita los scopes a los que quiere acceder.
  2. El usuario ve a través de la pantalla de autorización del navegador al que se solicita permiso por parte de la aplicación y envía la aprobación del acceso al servidor.
  3. El servidor da al usuario un código de acceso que mediante una redirección llega a la aplicación.
  4. La aplicación solicita acceso al servidor de autenticación enviándole el código obtenido en el paso previo y los datos propios de la aplicación.
  5. Finalmente, el servidor da a la aplicación el access token y el refresh token si aplica.

El siguiente es un diagrama simplificado del flujo Authorization Code y el diagrama correspondiente de la documentación de OAuth.

¿Cuándo se utiliza?

  • Tipo de aplicación consumidora: aplicaciones web, también puede utilizarse en aplicaciones móviles, pero sin almacenar el client secret y haciendo uso de PKCE extension, que protege de ataques que interceptan el código de autorización.
  • Grado de confianza de la aplicación: un tercero no confiable.
  • Interactuación por parte del usuario: consentimiento explícito a través de un navegador.
  • Tipo de comunicación: se utiliza habitualmente en comunicaciones cliente-servidor.

Implicit grant type

Este flujo es una simplificación del flujo de Authorization Code, el usuario también interviene directamente para dar su consentimiento explícito, pero no se hace uso de un código, sino que se utiliza el access token directamente.

Recibe el nombre de implícito porque toda la comunicación reside en el navegador, es decir, no hay un servidor backend.

¿Cómo funciona?

  1. La aplicación solicita al usuario el consentimiento expreso para acceder a los datos abriendo un navegador al usuario donde explicita los scopes a los que quiere acceder.
  2. El usuario ve a través de la pantalla de autorización del navegador a qué se solicita permiso por parte de la aplicación y envía la aprobación.
  3. El usuario es redirigido con un access token a la aplicación.

El siguiente es un diagrama simplificado del flujo Implicit y debajo el diagrama de la documentación de OAuth.

¿Cuándo se utiliza?

  • Tipo de aplicación consumidora: el caso tipo es una aplicación de una sola página, generalmente en Javascript que obtiene el access token sin pasar por un servidor entre medias y que no tienen forma de almacenar las claves de una forma segura.
  • Grado de confianza de la aplicación: un tercero no confiable, casos muy específicos ya que es el método menos seguro de todos.
  • Interactuación por parte del usuario: consentimiento explícito a través del navegador.
  • Tipo de comunicación: solo hay un cliente, sin servidor.

Se trata del flujo de OAuth menos seguro, de forma que su utilización debe limitarse a casos muy concretos (por ejemplo aplicaciones de una sola página en Javascript), ya que el token de acceso se devuelve en la URL directamente, sin utilizar un intermediario seguro.

Los tokens, en la mayoría de casos, son de corta duración ya que la mayoría se almacenan en el historial de navegación para mitigar el riesgo de que se filtren.

Otra desventaja es que no tiene un refresh token, ya que no existe un canal secundario, es necesario obtener un nuevo access token.

¿Qué flujo uso?

Como resumen, conviene tener algunas ideas claras de las partes involucradas en cada flujo:

Teniendo en cuenta lo anterior y las características de cada grant type, el siguiente diagrama de decisión pretende ayudar en la toma de decisión de qué método es el más adecuado para exponer una API en base al tipo de aplicación consumidora.

El diagrama no tiene porqué seguirse al pie de la letra simplemente son consejos, ya que habría que ver cada caso:

Casos de uso y conclusiones

  • Una parte fundamental del uso y consumo de las APIs es la seguridad y OAuth se ha convertido en en el framework de referencia para autorizar el acceso a las APIs, pero no es el único método, aunque sí el más extendido.
  • Las API Keys pueden utilizarse para casos específicos en los que la comunicación sea interna a la organización dueña de los datos que se exponen en la API y preferiblemente para operaciones consultivas.
  • Si se quiere incorporar una capa de autenticación y además hacerlo a través de diferentes IDPs, el método a utilizar es OpenId Connect.
  • OAuth, por su parte, se convierte en el método por defecto para autorizar el acceso a las APIs y es necesario conocer a fondo para identificar en qué casos utilizar cada flujo. Si se selecciona un grant type inadecuado, los atacantes pueden aprovechar esas vulnerabilidades de seguridad y crear problemas. Un ejemplo claro es utilizar en una aplicación alojada en el cliente una API expuesta mediante Client Credentials. El atacante puede obtener las credenciales simplemente inspeccionando el código fuente y suplantar la aplicación autorizada.
  • Desde la perspectiva de la aplicación consumidora, teniendo en cuenta dónde reside, su tipología y el grado de confianza, vemos algunos consejos para decidir qué utilizar del grant type:
    • Si no se requiere la autorización explícita del usuario final y la aplicación puede actuar como el propietario del recurso, el grant type adecuado es Client Credentials. Un caso típico son las comunicaciones servidor-servidor en el que ambos servidores se encuentran dentro de la organización.
    • Si se requiere autorización explícita del usuario:
      • Si la aplicación reside en el lado servidor o es una aplicación nativa que permite el acceso a usuarios terceros no confiables el grant type adecuado es Authorization Code.
      • Si la aplicación reside en el cliente, es una aplicación móvil nativa o de escritorio y es un tercero confiable el grant type adecuado es el Resource Owner Password Credentials. En este flujo es importante el grado de confianza entre los propietarios del recursos y el cliente ya que tienen que proporcionar los credenciales mediante la aplicación.
      • Si proporcionar las credenciales a la aplicación cliente es problemático, por ejemplo no pueden almacenarla de una forma segura (aplicaciones de una sola página en Javascript) o la autorización se realiza mediante un servidor de autorización externo, el grant type adecuado es el Implict Grant. Hay que tener cuidado con los datos que se exponen a través de este método ya que es el menos seguro de todos los que proporciona OAuth.

Referencias

Ingeniero Superior en Telecomunicaciones. Inicié mi carrera programando servicios hasta llegar al mundo de las APIs. Actualmente trabajo en Paradigma en el departamento de Arquitectura dentro del área de API Management y gobierno intentando promover las buenas prácticas en diseño y desarrollo de las APIs.

Ver toda la actividad de Noelia Martín

Escribe un comentario