Consumidores, Autenticación, y Autorización de APIs en Kong – IV: OAuth2

Kong Gateway permite la autenticación basada en OAuth 2.0, que evita el envío de contraseñas en texto claro en las llamadas a las APIs al utilizar Tokens y también evita el replay, además del resto de ventajas que proporciona OAuth 2.0. Kong es capaz de actuar como su propio servidor de identidad, proporcionando los endpoints necesarios para OAuth 2.0 (ej: /token, /authorize, etc.), permitiendo la implementación de los principales flujos de OAuth 2.0 (implicit, authorization code, client credentials, Password, y Refresh token). En este Post os explico en que consiste este mecanismo de autenticación, y cómo configurarlo en Kong utilizando Konga.

Continuando con la serie de Posts acerca de Kong, en esta ocasión vamos a ver el Pluign de OAuth 2.0 que proporciona Kong, cómo configurarlo en Kong utilizando Konga, y cómo probarlo con un curl.

Este Plugin convierte a Kong en su propio servidor de identidad, proporcionando los endpoints necesarios para OAuth 2.0 (ej: /token, /authorize, etc.) a través de HTTPS (por defecto, en el puerto tcp-8443), permitiendo así la implementación de los principales flujos de OAuth 2.0. Si lo que deseas es utilizar tu propio Servidor de Identidad, es decir, un Servidor de Identidad externo (ej: Azure AD, Azure AD B2C, Auth0, keycloak, etc.) con el que integrar tus APIs, existen otros Plugins que te pueden ayudar, pero requieren Kong Enterprise (la versión de pago).

Antes de continuar con este Post, es importante tener conocimientos básicos de OAuth 2.0, sus flujos de autenticación (Grant Types), así como de los access_token y Tokens JWT. En los enlaces contextuales anteriores, tienes más información.

Si quieres seguir este Post paso a paso, te recomiendo que te apoyes en el Docker Compose que compartí en GitHub (GitHub – ElWillieES – kong-docker-lab), y que sigas los anteriores Post (Introducción a Kong Gateway y Kong DashboardConsumidores, Autenticación, y Autorización de APIs en Kong – I, Consumidores, Autenticación, y Autorización de APIs en Kong – II: Autenticación HMAC, y Consumidores, Autenticación, y Autorización de APIs en Kong – III: Autenticación JWT) en los que configuramos la publicación de varios Servicios (APIs) en Kong así como la configuración de autenticación básica (Basic Auth) y de clave (Key Auth) con ACLs, así como la autenticación HMAC (Hash-Based Message Authentication) y JWT (JSON Web Token), y que utilizaré como punto de partida para los ejemplos que voy a realizar en este nuevo Post.

Configuración de Autenticación OAuth 2.0 en Kong usando Konga (Plugin OAuth2)

Como partimos de los laboratorios que hemos realizado en los Posts anteriores, queremos aprovechar lo que ya tenemos configurado para ver cómo convive, y mantener varios tipos de autenticación, la autenticación básica (Basic Auth) a nivel Global, la de clave (Key Auth) a nivel de una ruta de un servicio con ACLs, la HMAC (HMAC Auth) a nivel de otro servicio (service-c), y JWT (JWT Auth) y OAuth2 en otro servicio (service-b), de tal modo que puedan convivir todos estos métodos de autenticación aplicando cada uno sólo en los casos correctos, pudiendo haber usuarios que utilicen Basic Auth, API Key, HMAC, JWT, o OAuth2, indistintamente, en función del Endpoint y del propio usuario. Esto requiere alguna configuración especial, como se describe en la documentación de Kong (Kong Gateway – Allowing Multiple Authentication Methods), y como ya vimos y realizamos en un Post anterior (Consumidores, Autenticación, y Autorización de APIs en Kong – I)

Lo primero que vamos a hacer es habilitar la Autenticación OAuth2 en Kong, como mecanismo de autenticación para todas las APIs del Servicio B, por lo tanto, necesitamos habilitar el Plugin de OAuth2 a nivel de dicho Servicio. Para más información acerca del Plugin de OAuth2: Kong – Plugin – OAuth2

Vamos a hacerlo a través de Konga. Para ello en la sección Services, entramos en el Servicio service-b, y en la pestaña de Plugins, click en Add Plugin. Veremos que aparece el Plugin JWT que instalamos durante el laboratorio del anterior Post, y que van a convivir juntos.

Podemos elegir entre varios Plugins de Autenticación, en nuestro caso nos interesa el de OAuth2. Click en Add plugin para continuar.

La siguiente pantalla es importante, ya que podemos configurar varias cosas, en particuar en nuestro caso nos interesa:

  • Especificar un valor de Provision Key, o bien dejarlo en blanco, en cuyo caso se generará un valor aleatorio de forma automática. Este valor lo necesitaremos en las llamadas de algunos flujos OAuth (ver la documentación del Plugin para más detalle).
  • Configurar los Flujos OAuth2 que deseamos habilitar. Para este ejemplo, vamos a habilitarlos todos, siendo posible (y recomendable) ser más selectivos, y habilitar sólo los estrictamente necesarios. De hecho, más abajo para la demo vamos a probar únicamente Client Credentials, ya que es el más fácil de probar (basta con un simple curl a /token).
  • Configurar el ID del usuario anónimo (para que haga fallback y convivan múltiples mecanismos de autenticación en Kong).

Click Add Pluign para continuar.

Seguidamente, crearemos unas credenciales OAuth2 para un consumidor que usaremos para probar esta configuración. Recordemos que un Consumidor no tiene necesariamente que ser un Usuario, es decir, por ejemplo, un Consumidor podría ser una empresa (ej: un Cliente o un Proveedor) en la que creamos varias credenciales, para los diferentes usuarios y aplicaciones que consumen nuestras APIs desde dicha compañía. Incluso para una empresa, podríamos crear diferentes Consumidores con roles diferentes, y darle a cada Consumidor acceso sólo a las APIs que necesita.

En nuestro caso utilizaremos el consumidor willie que ya creamos anteriormente. Para ello, en la sección Consumers seleccionaremos el consumidor willie, en la página Credentials, iremos a la pestaña OAuth2, click en Create credentials. Debemos especificar un nombre para la credencial, una URL de Redirección (en este caso, vale cualquier URL aunque sea fake, ya que lo vamos a probar con el flujo Client Credentials, que no usa redirecciones), el client_id (en caso omiso se autogenerará), y el client_secret (en caso omiso se autogenerará). Click Submit.

Con esto, ya estaría todo configurado.

Probando la autenticación OAuth2 con el flujo Client Credentials

Antes de empezar, resumamos algunos detalles del flujo Client Credentials:

  • Permite obtener un access_token fuera del contexto de un Usuario, al tratarse de un flujo orientado a escenarios Machine-to-Machine (M2M).
  • Como consecuencia del punto anterior, identifica a la propia Aplicación en su nombre, no a un Usuario, enviando las credenciales de la Aplicación (Client ID y Client Secret).
  • Al no haber Usuario, no permite MFA ni cuentas delegadas.
  • No usa redirecciones.
  • Consiste en una única llamada POST al Endpoint /token, no se llama al Endpoint /authorize
  • Requiere el Client Secret

Lo primero que deberemos hacer, es una llamada al Endpoint /token, especificando el client_id, client_secret, y que deseamos utilizar el flujo de Client Credentials, lo cual nos devolverá un Token (ej: atWOP8I8RKGMiVa8Bnr5hj1cropQ7Cc8). La llamada tiene que ser a través de HTTPS (por defecto Kong utiliza el puerto tcp-8443 para esto), así que, como Kong utiliza por defecto un certificado auto-firmado que no es de confianza, deberemos utilizar la opción –insecure.

curl -X POST --insecure -i --location 'https://localhost:8443/service-b/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=xb3NGflUe0XqKw7NpFebIGIN' \
--data-urlencode 'client_secret=oMJTy9CE0XaiAmXwHXKiXJUg45' \
--data-urlencode 'grant_type=client_credentials'

Una vez obtenido el Token (ej: atWOP8I8RKGMiVa8Bnr5hj1cropQ7Cc8), podremos realizar la llamada al servicio.

curl -i --location 'http://localhost:8000/service-b' \
--header 'Authorization: Bearer atWOP8I8RKGMiVa8Bnr5hj1cropQ7Cc8'

Vamos a verlo en acción. A continuación se muestra como no podemos acceder al servicio sin autenticarnos correctamente, (nos devuelve un 401), seguidamente hacemos una llamada a Kong (siguiendo el flujo de Client Credentials) al Endpoint /token para autenticarnos y obtener un Token (la hacemos a través de HTTPS, con la opción –insecure ya que Kong por defecto utiliza un certificado auto-firmado que no es de confianza), y finalmente hacemos una llamada al servicio proporcionando el Token que acabamos de obtener, consiguiendo acceder con éxito.

Pasado un rato (unas horas) si intentamos hacer un replay, es decir, volver a ejecutar la misma petición con el mismo Token, podemos comprobar que no obtenemos acceso (nos devuelve un 401), ya que el Token ha expirado. Igualmente, si intentamos acceder utilizando autenticación básica (habilitada a nivel global) podemos acceder con éxito (conviven ambos mecanismos de autenticación, que es lo que hemos configurado).

Despedida y Cierre

Hasta aquí llega este Post, como continuación a los anteriores Posts Introducción a Kong Gateway y Konga Dashboard, Consumidores, Autenticación, y Autorización de APIs en Kong – I, Consumidores, Autenticación, y Autorización de APIs en Kong – II: Autenticación HMAC, y Consumidores, Autenticación, y Autorización de APIs en Kong – III: Autenticación JWT, en el que hemos seguido utilizando el Docker Compose compartido en GitHub, para quienes deseen seguir este laboratorio paso a paso: GitHub – ElWillieES – kong-docker-lab

Siguiendo con el tema de la autenticación en Kong, en esta ocasión hemos explicado cómo funciona la autenticación OAuth 2.0 que proporciona Kong Gateway en su versión Community, para seguidamente ver cómo configurarlo en un entorno de laboratorio, y hacer alguna prueba con algún curl para comprobar que está funcionando correctamente, comprobar la expiración del Token, la convivencia con otros mecanismos de autenticación (en caso de haberlos configurado), etc.

Quizás la necesidad principal que podamos tener, sea la de implementar OAuth 2.0 utilizando un servidor de identidad externo, algo que no podremos hacer con la versión Community (gratuita), pero para lo que si que existen Plugins disponibles en la versión Enterprise.

Poco más por hoy, como siempre confío que la lectura resulte de interés.