# Cómo controlar los refresh tokens de los agentes de IA

Un agente de IA nunca debería tener un refresh token. La regla parece severa hasta que observas qué hace el token: permite que un proceso siga obteniendo acceso después de que la aprobación humana original haya desaparecido de la vista. Un access token puede caducar rápido; un refresh token mantiene viva la relación.

El diseño útil no consiste en hacer que el agente proteja mejor una credencial bearer. Coloca la credencial en una capa de acciones propiedad de un proceso controlado por una persona. El agente solicita una acción externa concreta, la capa decide si esa ejecución puede realizarla, renueva el token solo cuando hace falta y devuelve el resultado. Así tienes un lugar donde aprobar, revocar e investigar el uso.

Una bóveda de contraseñas por sí sola no resuelve el problema. Una bóveda protege el almacenamiento. Una capa de acciones del agente gobierna el uso. Los equipos suelen confundir ambas funciones y después descubren que un token guardado en un almacén cifrado sigue estando disponible para cualquier proceso que sepa hacer la pregunta adecuada al almacén.

## Los refresh tokens de los agentes de IA cambian el límite de confianza

Los refresh tokens de los agentes de IA son peligrosos porque extienden la autoridad más allá del proceso del agente que los necesitó originalmente. Si un agente de programación puede leer un refresh token desde una variable de entorno, un archivo de configuración, un perfil del navegador o la respuesta de un gestor de secretos, puede usarlo mediante cualquier cliente HTTP que sea capaz de invocar. El token deja de pertenecer a una tarea delimitada y pasa a pertenecer a quienquiera que tome el control de ese proceso.

OAuth 2.0, RFC 6749, describe los refresh tokens como credenciales que sirven para obtener access tokens cuando el token actual caduca o deja de ser válido. La especificación los considera opcionales, pero eso no los hace inofensivos. Los proveedores los emiten porque repetir una autorización interactiva cada vez que hay que renovar un access token sería molesto. Precisamente por esa comodidad, un agente desatendido no debería poseer uno.

Mantén separadas estas tres funciones:

- El propietario de la cuenta es la persona o identidad de servicio cuya cuenta concedió el acceso.
- El solicitante de la acción es el proceso del agente que pide llamar a una API en ese momento.
- El custodio de la credencial es el componente que almacena el refresh token y se comunica con el endpoint de tokens.

Una misma persona o programa puede ocupar más de una función en una instalación pequeña, pero las funciones deben seguir existiendo. Si el mismo agente ocupa las tres, puede conectar una cuenta nueva, ampliar sus ámbitos, renovar el acceso indefinidamente y ocultar la acción entre solicitudes normales. Eso no es un diseño de autorización. Es un bearer token con un chatbot conectado.

He visto equipos decir «el agente solo necesita acceso de lectura» y después guardar en un archivo local `.env` un refresh token con acceso amplio a repositorios, correo electrónico o servicios cloud. El access token puede durar poco, pero el refresh token vuelve persistente el error. Un prompt injection no necesita convencer al modelo de exfiltrar una contraseña. Puede convencerlo de usar la autorización todavía válida para una solicitud que parezca razonable en ese contexto.

El límite debe estar antes de que las credenciales entren en el proceso del agente. El agente no recibe el valor de un token ni un sustituto ficticio que pueda intercambiar en otro lugar. Recibe una interfaz de operaciones: obtener este issue, crear este borrador, leer el estado de este despliegue, abrir esta sesión SSH con este host aprobado. La capa de acciones se ocupa de los detalles del protocolo que hay detrás de esa operación.

## Una persona debe ser propietaria de la autorización, no limitarse a aprobar un mensaje

La persona que puede aprobar una renovación debe estar identificada antes de crear la conexión OAuth. «Cualquier desarrollador puede hacer clic en permitir» funciona hasta que el propietario de una cuenta se marcha, un buzón compartido cambia de responsable o un agente vuelve a conectar un servicio con la identidad de otra persona.

En una cuenta SaaS personal, el propietario debe completar la autorización inicial y aprobar la reconexión después de una revocación o caducidad. En una cuenta operativa compartida, asigna un propietario responsable y un suplente que pueda revocarla. Para una identidad de máquina, el propietario del servicio debe autorizar el registro del cliente y sus ámbitos. No trates como intercambiables a una persona y una identidad de máquina solo porque ambas puedan llamar a la misma API.

Separa estas cuatro decisiones, que a menudo se reducen a un solo clic en el navegador:

1. Quién puede crear la autorización original.
2. Qué capa de acciones puede conservar el refresh token resultante.
3. Qué sesiones de agentes pueden solicitar acciones con esa autorización.
4. Quién puede revocar la autorización o aprobar una conexión nueva.

La pantalla original de consentimiento OAuth solo responde a la primera decisión, y a veces ni siquiera lo hace con claridad. Indica al proveedor que el titular de una cuenta autorizó a un cliente con determinados ámbitos. No indica a tu sistema local si un repositorio que no es de confianza, un nuevo subproceso del agente o una tarea nocturna puede usar esa autorización.

Un registro práctico de propiedad necesita algo más que el correo de la cuenta del proveedor. Guarda un registro local de la autorización con un ID opaco, el nombre del proveedor, la referencia de la cuenta, el conjunto de ámbitos, el propietario, el responsable suplente de la revocación, la fecha de conexión y las acciones que pueden solicitarla. No copies el refresh token en ese registro. El registro explica el token, pero no debe convertirse en otro almacén de secretos.

El caso incómodo es el acceso compartido. Un equipo suele conectar una cuenta de administrador porque es rápido y después permite que los agentes de todos los desarrolladores operen con ella. Esa decisión destruye la trazabilidad. Si la API admite cuentas de servicio, instalaciones de aplicaciones, identidades delegadas o tokens de proyecto con ámbitos limitados, usa esas opciones. Si no las admite, limita la capa de acciones a un grupo pequeño de operaciones aprobadas y registra quién es realmente el propietario de la cuenta compartida.

No permitas que un agente inicie por sí solo un flujo OAuth nuevo en el navegador. Puede mostrar una página legítima del proveedor, pero también dirigir a la persona hacia una cuenta más amplia, una selección de ámbitos más permisiva o un tenant diferente. Iniciar una conexión es una acción administrativa. Exige que la persona la inicie desde la capa de acciones y revise la cuenta y la lista de ámbitos antes de dar su consentimiento.

## La capa de acciones solo debe renovar para completar una acción aprobada

Una capa de acciones controlada debe intercambiar un refresh token únicamente cuando tenga una solicitud autorizada que necesite un access token actual. No debe ejecutar un bucle en segundo plano que renueve todas las credenciales «por si acaso». La renovación preventiva parece ordenada en el código y empeora la respuesta ante incidentes, porque mantiene vivas las autorizaciones sin una acción humana o del agente que las justifique.

El recorrido de una solicitud puede ser sencillo:

1. Una sesión del agente solicita una operación con nombre y proporciona los parámetros normales de la acción.
2. La capa de acciones identifica la autorización asociada a esa operación y comprueba si la sesión puede usarla.
3. Si no hay un access token en caché o está cerca de caducar, la capa envía el refresh token al endpoint de tokens del proveedor.
4. La capa llama a la API de destino con el access token y devuelve el resultado filtrado al agente.
5. La capa registra la acción y el evento de renovación sin guardar material de credenciales.

El agente nunca elige un endpoint de tokens, un identificador de cliente, una URL de callback ni una cadena de ámbitos. Esos valores pertenecen a la definición de conexión que aprobó la persona. Permitir que el agente los proporcione convierte tu gateway en un relay abierto de tokens.

Imagina que piden a un agente publicar una nota de lanzamiento en un gestor de proyectos. El agente solicita a la capa de acciones crear un issue en un proyecto concreto. La capa comprueba que la operación necesita una autorización del gestor para ese proyecto, verifica la sesión solicitante, renueva el access token si hace falta y publica la nota. El resultado puede ser el ID del nuevo issue y la referencia similar a una URL que devuelve el proveedor, no el bearer token usado para crearlo.

Ahora cambia el mensaje. Una instrucción maliciosa en un repositorio dice al agente que «verifique el acceso» enumerando todos los proyectos de la organización y creando un issue de prueba en cada uno. Si el agente tiene el refresh token, la instrucción puede convertirse en una serie directa de llamadas a la API. Si solo tiene la interfaz de operaciones con nombre, la capa puede rechazar solicitudes fuera del proyecto aprobado o exigir otra autorización humana antes de que continúe la sesión.

Esto no exige un lenguaje de políticas complicado. Hace falta un conjunto pequeño y comprensible de decisiones: qué proceso solicita la acción, qué autorización puede usar y si la acción requiere aprobación humana. Más opciones no hacen automáticamente más seguro el diseño. A menudo impiden que el operador sepa qué regla prevaleció.

Sallyport aplica esta separación al mantener las credenciales de API en su bóveda cifrada y ejecutar acciones HTTP o SSH mediante su conexión MCP, en lugar de devolver credenciales al agente.

## El tipo de autorización determina qué puedes automatizar de forma segura

Usa el flujo de código de autorización con PKCE para conectar una cuenta humana en una aplicación de escritorio o local. La persona inicia sesión con el proveedor, revisa la solicitud de consentimiento y vuelve a la aplicación local mediante la ruta de redirección registrada. PKCE vincula la respuesta de autorización al cliente que inició el flujo y reduce el valor de un código de autorización interceptado.

RFC 9700, OAuth 2.0 Security Best Current Practice, indica que los clientes públicos deben usar PKCE. También establece que los refresh tokens de clientes públicos deben usar una restricción del emisor o rotación de refresh tokens. Esta orientación importa para las integraciones con agentes porque una aplicación local suele comportarse como un cliente público. Incluir un secreto de cliente en una aplicación de escritorio no la convierte en un cliente confidencial. Cualquiera que tenga la aplicación puede extraer ese secreto.

Elige el flujo según la identidad que conectes:

- Usa el código de autorización con PKCE para la cuenta del proveedor de una persona.
- Usa credenciales de cliente para una identidad de servicio cuando el proveedor las admita y no haga falta delegar una cuenta humana.
- Usa el modelo de instalación o aplicación específico del proveedor cuando ofrezca acceso más limitado a un proyecto o una organización.
- Usa la autorización de dispositivo solo cuando el proveedor y tu entorno operativo lo requieran, y muestra a la persona exactamente qué identidad y qué conjunto de ámbitos está aprobando.

Las credenciales de cliente normalmente no generan refresh tokens porque el cliente puede solicitar un nuevo access token volviendo a autenticarse. Esto puede ser más seguro para una tarea autónoma si la identidad de servicio tiene permisos limitados y el material de autenticación del cliente permanece dentro de la capa de acciones. No uses las credenciales de cliente como excusa para entregar a un agente de programación un secreto con privilegios amplios.

El acceso sin conexión merece especial atención. Algunos proveedores de OpenID Connect exigen el ámbito `offline_access` antes de emitir un refresh token. Pídelo solo cuando una acción deba ejecutarse realmente después de que termine la sesión interactiva. Si habrá una persona presente en cada operación, un access token breve con una autorización nueva puede encajar mejor. Los equipos suelen pedir acceso sin conexión por defecto para evitar gestionar la caducidad. Así cambian una molestia por una credencial duradera.

Evita por completo las credenciales de contraseña del propietario del recurso. RFC 9700 desaconseja este tipo de autorización porque entrega la contraseña del usuario al cliente. Una capa de acciones no lo hace aceptable. Solo te da otro lugar donde perder una contraseña.

## La rotación solo sirve si el almacenamiento gestiona bien los reemplazos

La rotación de refresh tokens reduce el daño de un token copiado al hacer que cada renovación sustituya el token anterior. Un proveedor puede detectar la reutilización de un token antiguo e invalidar la familia de autorizaciones afectada. Esa detección ayuda, pero también puede bloquear tu integración legítima si la lógica de renovación es deficiente.

El fallo más común es una condición de carrera. Dos sesiones de agentes necesitan un access token casi al mismo tiempo. Ambas leen el mismo refresh token antiguo. La primera se renueva correctamente y recibe un valor nuevo. La segunda envía el valor antiguo un instante después. Según el proveedor, la segunda solicitud puede fallar o activar la detección de reutilización, que revoca toda la familia, incluido el token nuevo.

Evita la carrera con un único responsable de renovación por autorización. La capa de acciones debe serializar el trabajo de renovación para cada ID de autorización. La segunda llamada espera el resultado de la primera y después usa el access token recién guardado en caché, en lugar de enviar otra solicitud de token. Es un requisito de corrección, no una optimización.

Guarda el token de reemplazo antes de considerar correcta la renovación para usos posteriores. Un orden seguro sería:

1. Envía el refresh token antiguo al endpoint de tokens mediante TLS.
2. Valida la respuesta y asóciala con el proveedor y la autorización esperados.
3. Escribe el refresh token nuevo y sus metadatos en el almacenamiento cifrado mediante una única actualización persistente.
4. Marca el token antiguo como inutilizable en el estado local.
5. Libera las llamadas que esperan con el nuevo access token o con una ruta de solicitud nueva.

Si el proceso se bloquea después de que el proveedor rote el token, pero antes de que el almacenamiento local registre el reemplazo, puedes perder la autorización. Los reintentos no solucionan esto. La recuperación requiere que el propietario vuelva a conectar la cuenta de forma manual, por eso son importantes los registros del propietario y del responsable de revocación.

Algunos proveedores emiten un refresh token nuevo solo en ciertas ocasiones. Otros devuelven el mismo token. Tu código debe aceptar ambos comportamientos sin dar por hecho ninguno. Conserva el valor anterior solo hasta saber que la respuesta del proveedor y la escritura persistente se han completado correctamente. Nunca registres ninguno de los dos valores al depurar. Muchas filtraciones de tokens empiezan con una instrucción temporal de depuración que sobrevive a una versión publicada.

Los tokens vinculados al emisor pueden reducir el riesgo de reproducción al asociar un token con una clave criptográfica que conserva el cliente. DPoP, definido en RFC 9449, es un método posible. No elimina la necesidad de custodia. Si un agente puede usar tanto el refresh token como la clave privada de firma, sigue teniendo autoridad duradera. Conserva ambos materiales detrás de la capa de acciones y prueba el comportamiento del proveedor antes de confiar en esta restricción.

## La revocación necesita un operador identificado y un procedimiento probado

La revocación no es una opción que se activa una vez. Es una acción que alguien debe poder realizar bajo presión, cuando el panel del proveedor responde lentamente y nadie recuerda qué cuenta autorizó la integración.

Ofrece al propietario de la cuenta y al suplente designado una vía directa para revocar. Cuando revocan una autorización, la capa de acciones debe eliminar el refresh token local, invalidar cualquier access token en caché y detener las sesiones que podrían seguir solicitando esa autorización. Desactivar la interfaz del agente mientras la credencial sigue almacenada no es una revocación completa.

RFC 7009 define una solicitud de revocación de tokens OAuth. El proveedor publica su propio endpoint, pero la solicitud normalmente tiene este aspecto:

```http
POST /revoke HTTP/1.1
Host: authorization.example
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <client authentication>

token=<refresh-token>&token_type_hint=refresh_token
```

RFC 7009 indica a los servidores que devuelvan una respuesta correcta incluso cuando el token enviado ya no sea válido o sea desconocido. Esto impide que un atacante use el endpoint para averiguar si un token es válido. También significa que el operador no puede interpretar por sí solo un éxito HTTP como prueba de que la autorización tenía acceso activo. Registra que se envió la solicitud de revocación, elimina la credencial local y comprueba después el resultado con una llamada inocua al proveedor o con su registro de auditoría, si existe.

Prepara la revocación para estos casos: el propietario de la cuenta se marcha, se sospecha que una sesión del agente está comprometida, una instrucción de repositorio provocó una llamada externa inesperada, se retira una integración o un proveedor informa de la reutilización de un token. No esperes a que haya una filtración para decidir quién tiene autoridad para pulsar el botón.

Un access token ya emitido puede seguir siendo utilizable hasta que caduque. Algunos proveedores lo revocan de inmediato; otros no. Tu capa local puede dejar de emitir acciones nuevas al instante, que es el control que sí tienes. No prometas una invalidación global inmediata salvo que el proveedor la documente y la hayas probado.

Mantén separadas la revocación en el proveedor y la desactivación local. La desactivación local impide que tu capa de acciones use una autorización. La revocación en el proveedor le indica también al proveedor que la rechace. Durante un incidente, haz ambas cosas en este orden: corta primero tu propia ruta de ejecución y después envía la solicitud al proveedor. El primer paso está bajo tu control y no debe depender de una llamada de red externa.

## Un registro de auditoría debe explicar la intención, no solo el tráfico

Una lista de llamadas HTTP no puede decirte si una renovación fue correcta. Necesitas un registro que conecte la decisión humana, la sesión del agente solicitante, la referencia de la autorización y la acción externa resultante.

No escribas en el registro de auditoría refresh tokens, access tokens, códigos de autorización, aserciones de cliente ni cuerpos completos de API. Las cadenas de tokens son secretos. Los cuerpos completos de las respuestas pueden contener datos de clientes, contenido de repositorios o información personal. Registrarlos por comodidad crea otro almacén de credenciales y datos, más desordenado.

Un registro de evento útil incluye un ID de evento, la hora, el ID de sesión, la identidad del proceso solicitante, el ID de autorización, la referencia de la cuenta conectada, el nombre de la operación, el host del proveedor, el recurso solicitado, el conjunto de ámbitos registrado al conectar, la referencia de aprobación, la clase de resultado y un código de error si lo hubo. Para una renovación, registra que ocurrió y si tuvo éxito. No necesitas el valor del token para investigarla.

La diferencia entre un registro de acciones y un registro de credenciales es importante. El primero indica que una sesión concreta del agente solicitó el estado de un despliegue en un entorno determinado y que la capa de acciones lo permitió. El segundo indica qué autorización respaldó la solicitud y quién es su propietario. Mantén ambos registros relacionados mediante un ID de autorización opaco, pero no permitas que todos los operadores que pueden consultar el historial de acciones vean también los detalles de conexión de la cuenta.

Las pruebas de manipulación cambian la calidad de una investigación. Si un proceso local comprometido puede editar el mismo registro que escribe, un atacante puede borrar las entradas importantes. Usa un sistema de eventos de solo anexado con comprobaciones de integridad y verifica el registro de forma independiente del proceso que lo generó.

Sallyport proyecta sus registros de sesiones y actividad a partir de un registro de auditoría cifrado y encadenado mediante hashes, y `sp audit verify` comprueba esa cadena sin conexión y sin una clave de la bóveda.

Revisa el comportamiento con una frecuencia acorde con el poder de la autorización. Una autorización personal para un gestor de issues puede requerir una revisión ocasional. Una autorización capaz de cambiar la infraestructura de producción necesita una revisión después de cada conexión nueva, cada cambio de ámbitos y cualquier comportamiento inesperado del agente. La capa de acciones debe hacer que los registros sean suficientemente claros para que el propietario pueda responder: «¿Qué agente usó mi cuenta, para qué y con qué aprobación?»

## Los perfiles del navegador y los brokers genéricos de tokens crean desvíos silenciosos

Un perfil del navegador es un almacén de credenciales deficiente para un agente. Puede contener cookies de sesión, access tokens en caché, refresh tokens, selectores de cuenta y un estado de navegación no relacionado. Dar acceso a ese perfil a un agente es más amplio que delegar una acción de API y dificulta la limpieza, porque el estado del proveedor y el del navegador quedan mezclados.

Un broker genérico de tokens puede crear el mismo problema si acepta parámetros arbitrarios del endpoint de tokens. Los equipos suelen crear una API llamada `getToken(scope)` y sentirse más seguros porque el token ya no está en el proceso del agente. El broker sigue siendo una máquina expendedora de tokens si cualquier sesión puede pedir cualquier cuenta conectada o un ámbito arbitrario.

Haz que el solicitante pida una operación, no un token. «Crear una nota de lanzamiento en el proyecto A» tiene un propietario, un destino y un requisito de ámbitos que puedes inspeccionar. «Dame un token para tracker.write» deja demasiada autoridad en manos del solicitante.

No intentes resolverlo con un motor de reglas enorme antes de entender tus operaciones. Un catálogo breve de acciones aprobadas, vinculado a autorizaciones identificadas y a puntos de aprobación humana, es más fácil de revisar y más difícil de eludir. Añade complejidad solo cuando una necesidad operativa real lo exija.

También debes evitar compartir un mismo refresh token entre desarrollo, staging y producción. Las autorizaciones separadas hacen que la revocación sea menos drástica y los registros de auditoría menos ambiguos. Un agente de staging no debería conservar una ruta hacia producción porque ambos entornos usen por casualidad el mismo proveedor de identidad.

## Empieza con una tabla de propietarios y un simulacro de revocación

El primer artefacto útil es un inventario de autorizaciones, no el código. Crea una fila para cada refresh token que tus agentes puedan hacer que se use. Incluye el proveedor, la referencia de la cuenta, el ID de autorización, los ámbitos, la ubicación de la capa de acciones, el propietario de la cuenta, el suplente para revocar, el método de creación, el último uso confirmado y el procedimiento local de desactivación. Si no puedes completar una columna, todavía no controlas esa autorización.

Después, ejecuta un simulacro de revocación con una integración de bajo riesgo. Haz que el propietario desactive la autorización localmente, la revoque en el proveedor y trate de realizar una acción normal con el agente. Confirma que la capa de acciones bloquea la solicitud, que la reconexión requiere una acción humana explícita y que el registro de auditoría identifica la sesión anterior. El ejercicio revela rápidamente supuestos erróneos: endpoints del proveedor desconocidos, propietarios de cuentas sin identificar, tokens almacenados en ordenadores antiguos de desarrolladores y access tokens en caché que duran más de lo esperado localmente.

Establece una revisión de caducidad para las autorizaciones que no tengan límites impuestos por el proveedor. El acceso prolongado a veces es necesario para el trabajo desatendido, pero el acceso indefinido debe ser una excepción deliberada con un propietario identificado. Cuando un equipo no puede nombrar al propietario, la autorización no debería seguir siendo utilizable.

El criterio es sencillo: un agente puede solicitar trabajo, pero no debe heredar la capacidad de una cuenta para renovarse por siempre. Coloca la credencial de renovación donde una persona pueda controlar su uso y convierte la revocación en una acción practicada, no en una búsqueda de emergencia entre pestañas del navegador.
