Tema representativo de entrevista

Entrevista de backend: ¿Cómo diseñarías el intercambio de tokens OAuth para llamadas de servicios delegadas?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Un API gateway de SaaS multi-inquilino llama a un servicio de facturación en nombre de un usuario autenticado. La plataforma de identidad emitió un token de acceso para el gateway, pero el gateway no debe reenviar ese token a todos los servicios downstream. Diseña un endpoint de intercambio de tokens OAuth y explica cómo evitas la escalada de privilegios, el comportamiento de diputado confundido (confused deputy), la reproducción (replay) y el desfase de revocación.

Problema y contexto

Un API gateway de SaaS multi-inquilino llama a un servicio de facturación en nombre de un usuario autenticado. La plataforma de identidad emite un token de acceso upstream para el gateway; el servicio de facturación acepta únicamente su propia audiencia. El gateway necesita un token downstream más acotado mientras preserva una declaración auditable de quién actuó en nombre de quién.

Diseña el endpoint de intercambio, las reglas de validación, el mapeo de claims, el almacenamiento en caché, el manejo de errores, la revocación y el monitoreo. Asume que el gateway es un cliente controlado del lado del servidor y que los navegadores nunca tienen en su poder el token downstream. El servicio de facturación debe rechazar tokens destinados a otro servicio.

Tu diseño debe preservar cinco invariantes:

  1. El servicio de intercambio solo acepta tokens de sujeto validados que tengan permiso para ser intercambiados.
  2. La nueva audiencia, el alcance (scope), el inquilino (tenant) y el alcance del recurso no pueden ser más amplios que la autorización upstream.
  3. El sujeto y el actor permanecen distinguibles y rastreables; un servicio no puede hacerse pasar por un usuario.
  4. Un servicio downstream confía únicamente en su propio emisor, audiencia y claves de firma.
  5. La revocación, la expiración, la rotación de claves y los límites de auditoría tienen límites de tiempo medibles.

Qué está evaluando el entrevistador

Comienza distinguiendo entre intercambio de tokens, reenvío de tokens, suplantación (impersonation) y delegación. El RFC 8693 define un Security Token Service HTTP/JSON. Una solicitud puede contener un subject_token y opcionalmente un actor_token; la respuesta extiende una respuesta normal del endpoint de tokens de OAuth. El protocolo no otorga una autoridad más amplia por sí mismo.

La siguiente señal es la disciplina de la audiencia. El gateway no debe reenviar un token de portador (bearer token) dirigido a sí mismo hacia los servicios de facturación, búsqueda y exportación. Cada token downstream necesita una única audiencia y solo los scopes requeridos para la llamada.

La tercera señal es la relación de proxy. El intercambio se permite solo cuando la política establece que el actor puede actuar en nombre del sujeto. Claims como may_act y act necesitan un emisor confiable o una fuente de política local. Copiar un sub o tenant_id arbitrario proporcionado por el cliente en un nuevo token constituye una escalada.

Finalmente, analiza los modos de falla: una caché de autorización desactualizada, un servicio downstream que verifica firmas pero no la audiencia, tokens en logs, un token de actualización (refresh token) entregado al gateway y una revocación upstream que sigue surtiendo efecto hasta que expire el TTL downstream.

Preguntas para aclarar primero

  • ¿Quién es el sujeto y quién es el actor? Aquí el sujeto es el usuario y el actor es el API gateway; la suplantación mediante cuenta de servicio requiere una política explícita.
  • ¿Quién consume el token intercambiado? ¿Facturación es la única audiencia o se permiten múltiples recursos? Múltiples audiencias amplían el radio de impacto.
  • ¿Cómo se reduce el alcance? El token upstream puede tener billing:read billing:write; ¿cuál de ellos necesita esta solicitud?
  • ¿Dónde se verifica el límite del inquilino? ¿Qué almacenes de identidad, sesión y recursos son autoritativos? Nunca confíes en un campo de inquilino en el cuerpo de la solicitud.
  • ¿Cuál es el objetivo de revocación? Por ejemplo, detener nuevos intercambios en menos de cinco segundos y limitar los tokens downstream existentes a dos minutos.
  • ¿Necesita el gateway un refresh token? Una llamada delegada normalmente necesita un token de acceso de corta duración; un refresh token de larga duración requiere una revisión de amenazas independiente.

Una respuesta de 30 segundos

“Haría que el gateway llame a un endpoint de tokens estándar con un subject_token de usuario, un actor_token del gateway, una audiencia fija de facturación y el alcance mínimo. El servicio de intercambio valida el emisor, la firma, exp, nbf, la autenticación del cliente, la política de delegación del sujeto y el estado del inquilino. Una tabla de políticas mapea los scopes upstream a un scope downstream permitido. El nuevo token contiene solo la audiencia de facturación, una expiración corta, el contexto del inquilino y la relación sujeto/actor; nunca copia claims no verificados.

El servicio de facturación confía únicamente en su emisor, claves de firma y audiencia, y realiza la autorización a nivel de recurso. Las decisiones de intercambio pueden almacenarse en caché brevemente, pero los eventos de revocación y un TTL corto deben cumplir con el objetivo establecido. Los cuerpos de los tokens, las solicitudes de intercambio y los secretos de los actores se redactan. Los errores son genéricos; los registros de auditoría conservan el ID de solicitud, sujeto, actor, audiencia, scope y versión de la política.”

Diseño paso a paso

Paso 1: Definir el token y el límite de confianza

El servicio de intercambio es un servidor de autorización o un STS confiable, no un asistente arbitrario del gateway. Configura emisores upstream permitidos, JWKS, métodos de autenticación de clientes, audiencias downstream y versiones de políticas. El gateway se autentica con mTLS, un JWT de clave privada u otro método aprobado; una cadena estática por sí sola no es prueba de autoridad de delegación.

La solicitud mínima puede verse así:

text
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=...
subject_token_type=urn:ietf:params:oauth:token-type:access_token
actor_token=...
actor_token_type=urn:ietf:params:oauth:token-type:access_token
audience=https://billing.internal
scope=billing:read

El RFC 8693 trata al solicitante como el cliente en el intercambio. Un servidor de recursos puede actuar temporalmente como ese cliente para cambiar un token entrante por uno apropiado para un servicio backend. El rol no otorga por sí mismo nuevos permisos.

Paso 2: Validar sujeto y actor por fuente

Selecciona un validador por tipo de token, luego verifica una lista de algoritmos permitidos, emisor, exp, nbf, cliente requerido, tipo de token y estado de revocación. Almacena en caché el JWKS por emisor y rótalo por kid; una clave desconocida puede desencadenar una actualización controlada, nunca una degradación de algoritmo.

El sujeto es el usuario o la carga de trabajo representada. El actor es el gateway que realmente inició el intercambio. La política debe responder si este actor puede actuar en nombre de este sujeto en esta audiencia, no simplemente si el actor es un servicio conocido. El claim may_act de RFC 8693 puede expresar un actor autorizado; el token intercambiado puede expresar el actor actual con act. Ambos claims necesitan un emisor confiable o una política local.

No trates los campos sub, tenant_id o roles del cuerpo de la solicitud como hechos de identidad. Reconstruye el contexto a partir de tokens validados y del directorio de inquilinos autoritativo, y rechaza datos de sujeto faltantes o conflictivos.

Paso 3: Calcular una autorización monotónicamente más acotada

Expresa la autorización como una intersección restringida:

text
issued_scope = requested_scope
             ∩ subject_allowed_scope
             ∩ actor_allowed_scope
             ∩ audience_policy_scope
             ∩ tenant_state_scope

Rechaza un scope solicitado que esté vacío o sea excesivamente amplio; no generes silenciosamente un valor predeterminado más amplio. La audiencia proviene de un registro de servicios, no de una URL arbitraria proporcionada por el gateway. Cada audiencia vincula claims, scopes, TTL y tipos de recursos permitidos.

El estado del inquilino, un usuario deshabilitado, la titularidad de la cuenta de facturación y las acciones de alto riesgo pueden requerir una verificación de política en línea. Un token tenant_id es solo parte del contexto validado; el servicio de recursos aún lo compara con la titularidad. Si una solicitud necesita varios servicios, prefiere varios intercambios de corta duración en lugar de una única audiencia universal.

Paso 4: Emitir un token downstream verificable y de corta duración

El token de acceso debe contener iss, sub, aud, exp, iat, scope, identidad del inquilino, ID de cliente, versión de la política y relación de actor. Su expiración no debe exceder la vida útil restante upstream ni la ventana de riesgo del negocio. No devuelvas un refresh token como resultado ordinario de un intercambio.

El servicio de facturación fija el emisor, la audiencia, el JWKS y los algoritmos permitidos, y realiza la autorización de recursos en cada solicitud. La validación de firma sin validación de aud permite que un servicio acepte un token emitido para otro. Un token restringido por el emisor (sender-constrained) puede garantizar además que copiar un valor de portador sea insuficiente.

Paso 5: Coordinar caché, revocación y rotación de claves

Almacena en caché los metadatos del emisor, JWKS y los resultados de políticas de corta duración solo cuando la clave incluya emisor, sujeto, actor, audiencia, scope, inquilino y versión de la política. Nunca reutilices la decisión de autorización de un inquilino para otro. Una revocación actualiza primero a la autoridad y publica un evento de invalidación; el endpoint de intercambio deja de emitir en un plazo de cinco segundos, y los nuevos tokens downstream tienen un TTL máximo de dos minutos. Facturación puede elegir entre introspección o verificación con TTL corto según el nivel de riesgo.

Prueba mensajes de invalidación perdidos, reinicios de nodos y retraso de replicación. La rotación de JWKS necesita una superposición acotada y un kid rastreable. Revocar una clave de firma afecta a todos los tokens que firmó; no sustituye la revocación a nivel de sujeto.

Paso 6: Manejar errores, reproducción y disponibilidad

Devuelve un error uniforme de clase invalid_grant u invalid_target para emisor desconocido, expiración, audiencia incorrecta, sujeto no delegable, scope insuficiente y política no disponible. No reveles si existe un sujeto; mantén un ID de solicitud y un código de motivo seguro internamente.

Las solicitudes de intercambio contienen material de portador y no deben ingresar en URLs, logs ordinarios, atributos de rastreo o reportes de errores. Si el token upstream se puede reproducir, un atacante que robe el tráfico del gateway puede repetir intercambios. TLS, restricciones del emisor, TTLs cortos, límites de tasa y señales de riesgo reducen la ventana de exposición. Si el almacenamiento de políticas no está disponible, opta por fallar de forma cerrada (fail closed) para escrituras de alto riesgo. Cualquier mecanismo de respaldo para lecturas de bajo riesgo necesita una antigüedad máxima de política desactualizada.

Paso 7: Auditar la cadena de sujetos y el límite del inquilino

Registra request_id, sujeto, actor, cliente, inquilino, audiencia, scope solicitado y emitido, ID de token, versión de política, ID de clave del emisor y decisión. Nunca registres el cuerpo del token. Los logs downstream hacen referencia al ID de token y al ID de solicitud para que una llamada del gateway pueda conectarse a la acción de un usuario.

El servicio de recursos no debe confiar únicamente en un encabezado X-Tenant-ID proveniente del gateway. Lee el contexto del inquilino del token firmado, luego verifica la titularidad del recurso, el estado de la cuenta de facturación y las reglas de aprobación. Añade pruebas adversariales para acceso entre inquilinos, comportamiento de diputado confundido, expansión de scope, audiencia incorrecta y reproducción de un token antiguo.

Paso 8: Desplegar con evidencia por fases

Registra una audiencia y un scope fijos para un inquilino de prueba y demuestra que un token antiguo no puede acceder a facturación. Realiza un despliegue canario del nuevo emisor y clave mientras observas la tasa de rechazo de intercambio, la latencia de la política, el TTL del token, los errores de audiencia, los aciertos en caché y la propagación de la revocación. Expande a inquilinos de producción solo después de que las mediciones se mantengan firmes.

Mantén un interruptor de reversión que detenga nuevas emisiones y restaure una configuración de cliente validada como correcta. No reviertas deshabilitando las comprobaciones de audiencia downstream ni eliminando registros de auditoría.

Respuesta modelo de alta calidad

“Trato al servicio de intercambio como un STS confiable. El gateway envía un subject_token de usuario autenticado por el cliente, su propio actor_token, una audiencia de facturación fija y el scope más pequeño. El servicio valida cada emisor, firma, claims temporales, tipo de token, cliente y regla de delegación, y luego intersecta el scope solicitado con la política de sujeto, actor, audiencia y estado del inquilino. Rechaza audiencias arbitrarias y cualquier solicitud que amplíe la autoridad.

El token downstream es únicamente para facturación, expira a más tardar al mismo tiempo que el token upstream y registra sujeto, actor, inquilino, scope, versión de política e ID de token. Facturación fija su emisor, JWKS y audiencia, y sigue realizando la autorización de inquilinos a nivel de recurso. Los tokens y las solicitudes de intercambio nunca entran en los logs; los registros de auditoría contienen únicamente la cadena y los metadatos de decisión.

La revocación actualiza a la autoridad y transmite la invalidación, deteniendo nuevos intercambios en menos de cinco segundos. Los tokens downstream duran como máximo dos minutos, eligiendo introspección o validación con TTL corto según el riesgo. Las claves de caché incluyen todas las dimensiones de identidad y política, y la rotación de JWKS tiene una superposición acotada. El intercambio de tokens acota la autoridad y preserva la rendición de cuentas; no copia la identidad del usuario en cada servicio.”

Errores comunes

  • Reenviar el token de portador upstream. Su audiencia es incorrecta y una filtración se propaga lateralmente; intercambia un token acotado por recurso.
  • Verificar solo la firma. Una firma válida no prueba emisor, audiencia o scope.
  • Fusionar sujeto y actor. El servicio downstream no puede distinguir al usuario del servicio proxy, por lo que la auditoría y la revocación pierden sentido.
  • Confiar en el tenant_id del cuerpo de la solicitud. Un atacante puede seleccionar otro inquilino; derívalo de la identidad validada y la titularidad del recurso.
  • Asumir que un actor autorizado a intercambiar puede representar a cualquiera. La delegación necesita una política explícita y una fuente confiable.
  • Emitir un refresh token por defecto. El gateway necesita un token de acceso de corta duración; una credencial de larga duración amplía la ventana de exposición.
  • Almacenar en caché sin todas las dimensiones o con un TTL largo. La autorización puede cruzar inquilinos o sobrevivir a la revocación; acota las claves, versiones y propagación.
  • Registrar tokens o solicitudes de intercambio en los logs. Los valores de portador son reproducibles; registra solo IDs de tokens, metadatos públicos y códigos de motivo.
  • Usar un solo token para todos los servicios downstream. La audiencia y el scope se vuelven demasiado amplios; realiza intercambios por separado.
  • Probar únicamente los casos de éxito. La expiración, audiencia incorrecta, revocación, rotación de JWKS, reinicios y fallas de políticas exponen el límite real.

Preguntas de seguimiento y respuestas de referencia

¿Qué resuelven may_act y act?

may_act indica qué actor está autorizado por el subject token para actuar; act indica quién actúa actualmente en nombre de quién en el nuevo token. Ninguno reemplaza las comprobaciones de firma, emisor, audiencia o autorización local, y ambos requieren una fuente confiable.

¿Por qué no reenviar el token del usuario a facturación?

El token upstream suele estar dirigido al gateway y puede cubrir múltiples recursos. El reenvío amplía la exposición de audiencia y permisos. El intercambio emite un token auditable y de corta duración exclusivamente para facturación.

¿Debería facturación usar introspección en línea?

Depende de los objetivos de revocación, el tráfico y la disponibilidad. Las escrituras de alto riesgo pueden usar introspección; las lecturas ordinarias pueden usar un JWT con TTL corto. Mide el peor retraso posible; no se pueden afirmar simultáneamente el almacenamiento en caché fuera de línea y la revocación inmediata sin un mecanismo acotado.

¿Qué pasa si el servicio de políticas no está disponible?

Falla de forma cerrada (fail closed) para intercambios de alto riesgo. Una lectura de bajo riesgo puede usar una caché de políticas desactualizada explícitamente acotada, con el mecanismo de respaldo visible en el monitoreo y la auditoría. Permitir por defecto convierte un incidente de disponibilidad en una escalada de privilegios.

¿Cómo se evita una confusión en la caché multi-inquilino?

Incluye emisor, sujeto, actor, inquilino, audiencia, scope y versión de la política en la clave de caché, y continúa verificando la titularidad del recurso. Una clave basada únicamente en el ID de usuario o en la audiencia puede reutilizar la decisión de un inquilino para otro.

El token upstream ha sido revocado, pero el token downstream sigue siendo válido. ¿Qué sucede entonces?

Detén los nuevos intercambios de inmediato y permite que el servicio downstream realice introspección o consuma eventos de invalidación según el riesgo. Si solo verifica fuera de línea, limita el TTL a la ventana máxima aceptada y audita las operaciones en ese intervalo; las operaciones confirmadas no se pueden revertir.

¿Cómo se realiza una reversión (rollback) de forma segura?

Detén los nuevos intercambios, retira la versión de política o la audiencia problemática, mantén la validación acotada para la clave de firma anterior y restaura una configuración de cliente confirmada como correcta. Nunca deshabilites las comprobaciones de audiencia ni elimines evidencia de auditoría como un atajo.

Fuentes públicas

Preguntas relacionadas