Jesús Torres

Todos los proyectos

Gatekeeper: acceso delegado a APIs de terceros

Cómo Gatekeeper mantiene en el servidor las credenciales de APIs de terceros y da a cada usuario acceso solo a los proveedores concedidos.

Stack
TypeScript, Express, MongoDB, Redis
Enlaces
gatekeeper.jatv.dev (live demo)
gitlab.com/JTOpenSource/tools/Gatekeeper

El problema

Una API externa suele darte una sola credencial: un client ID con su secreto, o un token. En cuanto varias personas o servicios necesitan esa API, la credencial se copia en cada uno. Rotarla obliga a encontrar todas las copias. Quitarle el acceso a una persona obliga a rotarla para todos.

La idea

Separar dos cosas que suelen ir juntas: tener una credencial y tener permiso para usarla. Gatekeeper guarda las credenciales de los proveedores. Los usuarios solo tienen una sesión de Gatekeeper, y un administrador decide a qué proveedores puede llamar cada uno. La app consumidora nunca ve el secreto del proveedor.

Tu apptiene un token de Gatekeeperlos secretos no cruzan esta líneaGatekeeper¿quién llama?¿tiene este proveedor?descifrar secretoAdmin + TOTP

concede, revoca, guarda secretos

API externaOAuth / bearer / basic

Puedes probarlo en la demo en vivo: entras como un worker con un proveedor de prueba. Si lo llamas recibes sus datos; si pides cualquier otro, Gatekeeper responde 403. El token del proveedor nunca llega a la página.

Cómo fluye una llamada

  1. El usuario inicia sesión en Gatekeeper y recibe un token de sesión. La sesión se registra en Redis.
  2. La app envía a Gatekeeper el nombre del proveedor, el método, la ruta y el cuerpo de la llamada que quiere hacer.
  3. Gatekeeper verifica la sesión, carga al usuario desde la base de datos y comprueba que ese proveedor esté en su lista. Si no está, responde 403.
  4. Carga el registro del proveedor y descifra su secreto, guardado con AES-256-GCM, en el momento de usarlo.
  5. Se autentica como ese proveedor espera (OAuth client credentials, bearer token o basic auth), reenvía la llamada y devuelve la respuesta.

Los permisos se leen de la base de datos en cada llamada, no van dentro del token. Revocar un proveedor tiene efecto en la siguiente petición, no cuando caduca el token.

Administración

Los administradores crean y eliminan usuarios, cambian roles entre admin y worker, y conceden o revocan el acceso a cada proveedor por usuario. Toda operación de administración pasa por un rate limiter, una verificación de sesión, una de rol y un código TOTP.

Como las sesiones viven en Redis y no solo dentro del token, cerrar sesión invalida de una vez todas las sesiones activas del usuario.

Diagrama de Gatekeeper con tres flujos. Usuario nuevo: pide una cuenta al administrador, recibe credenciales y cambia la contraseña. Administrador: inicia sesión, configura Google Authenticator, crea usuarios y concede acceso a proveedores. Usuario: inicia sesión, pide acceso a un proveedor, ejecuta la llamada a la API y recibe los datos. Todos pasan por el núcleo de Gatekeeper, que valida el JWT y los permisos de administrador, con Redis para sesiones y MongoDB para usuarios y credenciales cifradas.
Los tres flujos tal como los dibujé al diseñar Gatekeeper: alta, administración y la llamada a través del proxy. El diagrama está en inglés.

Sobre qué está construido

TypeScript y Express, MongoDB para usuarios y proveedores, Redis para sesiones. El cifrado, las sesiones, el cliente HTTP y el acceso a datos vienen de tslib, mi librería compartida de TypeScript, así que las mismas piezas se reutilizan en mis otros servicios.

La consola web es una app SvelteKit pequeña que funciona como backend for frontend: el navegador nunca habla con la API, el token de sesión vive en una cookie httpOnly y los secretos de los proveedores son de solo escritura en las pantallas de administración. Corre en el mismo servidor que la API, así que los límites de peticiones siguen contando a cada visitante y no a la consola.

Compromisos

Cada llamada que pasa por el proxy depende ahora de Gatekeeper: si cae, esas integraciones caen también, y añade un salto de red. Centralizar los secretos es el objetivo, y también convierte al servidor de Gatekeeper en la máquina que más hay que proteger.

Es pequeño a propósito. Autentica, autoriza y reenvía; no es una plataforma de gestión de APIs.