# ¿Por qué los archivos de tokens de actualización de OAuth son credenciales de producción?

Un archivo `auth.json` copiado no es un residuo de configuración. Si contiene un token de actualización, es una credencial de producción que puede seguir creando tokens de acceso después de que la persona que lo copió se haya ido a casa. Llamar «sin interfaz» a la máquina no cambia eso. Solo elimina el aviso del navegador que habría recordado a alguien que debía pensar en la propiedad de la credencial.

He visto equipos proteger cuidadosamente una clave de API y luego enviar un archivo de token de actualización a un host de compilación como adjunto en un chat porque el token de acceso que contenía caducaba pronto. Es justo al revés. El token de acceso de corta duración suele ser la parte menos interesante del archivo. La ruta de renovación es lo que un atacante, un agente con permisos excesivos o un trabajo nocturno sin responsable puede seguir utilizando.

## Un archivo de token de actualización es un paquete de credenciales

Un archivo de token de actualización de OAuth es un paquete de credenciales porque normalmente contiene suficiente información para obtener un nuevo token bearer sin que haya una persona presente. Los campos exactos varían según la biblioteca cliente, pero la combinación peligrosa resulta familiar: un token de actualización, un identificador de cliente, un endpoint de tokens, los alcances concedidos y, en ocasiones, un secreto de cliente o una aserción específica del dispositivo.

No dejes que la extensión del archivo haga que el riesgo parezca menor. JSON es solo un envoltorio. Un archivo llamado `.cache/session.json`, `token-store.json` o `auth.json` merece el mismo tratamiento que una clave SSH privada cuando puede renovar el acceso a un servicio de producción.

El OAuth 2.0 Authorization Framework, RFC 6749, describe los tokens de actualización como credenciales que se usan para obtener tokens de acceso. También indica que el servidor de autorización puede emitir un token de actualización nuevo y que el cliente debe descartar el anterior. Es fácil pasar por alto esa última frase como un detalle del protocolo. En un sistema desatendido, es un requisito operativo: dos trabajadores que creen tener el archivo actual pueden acabar compitiendo por la identidad de una credencial.

Separa estas tres cosas en tu inventario:

- Un token de acceso autoriza una solicitud durante un periodo limitado.
- Un token de actualización autoriza la renovación, a menudo durante muchas vidas útiles de tokens de acceso.
- Un cliente OAuth identifica al software que solicita la renovación.

Los equipos suelen mezclar las dos primeras y después presentan el argumento equivocado sobre la caducidad. Un token de acceso de cinco minutos no hace seguro un token de actualización copiado. Puede significar simplemente que el archivo copiado proporciona a un intruso tokens nuevos en lotes de cinco minutos.

Una entrada del inventario de producción debe responder a algo más que «¿qué servicio usa esto?». Registra el servidor de autorización, el identificador del cliente OAuth, el servidor de recursos, el sujeto o la cuenta de servicio, los alcances concedidos exactos, el entorno, la fecha de emisión si está disponible, el propietario de la renovación, la ruta de ejecución aprobada y el método de revocación. Si no puedes completar esos campos, no tienes una credencial lista para uso autónomo. Tienes un archivo que funcionó por casualidad durante las pruebas.

## El trabajo sin interfaz facilita perder la propiedad

Un agente sin interfaz necesita un acuerdo de renovación que nombre a un propietario responsable. El fallo habitual empieza cuando un desarrollador autoriza una herramienta local con su propia cuenta y después copia la caché a un servidor porque el servidor no puede completar el flujo del navegador. El trabajo funciona, así que la copia se vuelve permanente.

Ahora haz las preguntas que la gente evita porque resultan incómodas. ¿El token representa al desarrollador, al equipo o al trabajo? ¿Quién puede revocarlo sin romper el trabajo de otra persona? ¿Qué repositorio o instrucción del agente indica al trabajo dónde encontrarlo? ¿Puede un empleado que se marcha invalidar la identidad que hay detrás? ¿La página de consentimiento del proveedor muestra una cuenta personal aunque el trabajo se comporte como un servicio?

«La cuenta de la plataforma es la propietaria» no es una respuesta a menos que esa cuenta tenga un administrador documentado, un procedimiento de recuperación y privilegios limitados. Un token copiado desde un inicio de sesión personal es peor que una clave de API visible en un aspecto: suele llegar como un archivo de caché opaco, por lo que los revisores no pueden ver qué permisos se han incorporado.

Usa una identidad de servicio dedicada cuando el proveedor la admita. Dale a esa identidad el conjunto mínimo de permisos sobre recursos que permita terminar el trabajo. Registra un cliente OAuth separado para cada límite de confianza importante, como desarrollo, preproducción y producción. No uses un cliente amplio y una concesión de consentimiento amplia solo porque sea cómodo renovar.

Conviene mantener clara una distinción: la identidad del cliente OAuth y la identidad del recurso son controles distintos. Un identificador de cliente indica qué software solicitó un token. El sujeto y los alcances indican a qué recursos puede acceder el token y qué puede hacer. Un equipo que crea un cliente dedicado, pero sigue autorizándolo como administrador humano, mejora un poco la atribución y deja intacto el problema de los privilegios.

Para un agente, escribe un registro sencillo de propiedad junto a la documentación del despliegue, no dentro del archivo de tokens:

```text
Credential name: billing-export-prod
OAuth client: agent-billing-prod
Resource identity: svc-billing-export
Scopes: reports.read, exports.write
Renewal owner: platform-oncall
Execution path: production job runner through credential broker
Revocation: authorization server admin console and RFC 7009 endpoint
```

Este registro es deliberadamente aburrido. Por eso resulta útil a las dos de la madrugada. Permite a un operador revocar la concesión correcta sin adivinar si el archivo pertenecía al antiguo portátil de un desarrollador, a una prueba de preproducción o al trabajo que ahora le está avisando.

## Guarda la ruta de renovación fuera del espacio de trabajo del agente

El proceso del agente no debería leer un archivo de token de actualización. Si un agente puede leer la cadena, puede imprimirla, escribirla en un registro, incrustarla en un parche, enviarla a una herramienta remota o dejarla en un informe de fallo. Las instrucciones que piden no revelar secretos no cambian la capacidad del proceso para exfiltrar los datos que puede leer.

Los permisos del sistema de archivos siguen siendo importantes, pero son una capa de contención posterior a la decisión arquitectónica. Un modo como `0600` mantiene fuera a otras cuentas locales en un host Unix convencional. No impide que el proceso autorizado del agente, sus complementos, sus procesos secundarios, su depurador o un trabajo de copia de seguridad lean el archivo. Tampoco explica por qué ese host tiene una credencial de renovación de producción.

Guarda el token de actualización en un gestor de secretos, un almacén de credenciales del sistema operativo o un intermediario local que el agente no pueda consultar para obtener valores sin procesar. El intermediario debe aceptar una solicitud de acción limitada, obtener o renovar internamente la credencial, llamar al endpoint de recursos aprobado y devolver el resultado que necesita el agente. Una solicitud puede tener este aspecto:

```json
{
  "action": "create_export",
  "target": "billing-api",
  "parameters": {
    "report_date": "2026-07-23"
  }
}
```

El agente recibe una respuesta como esta, no un token:

```json
{
  "status": "accepted",
  "export_id": "exp_4821",
  "report_date": "2026-07-23"
}
```

Este límite evita un error frecuente: montar un directorio de secretos en cada contenedor de trabajo y llamarlo acceso controlado. El montaje deja el secreto disponible para cada biblioteca, comando de shell, extensión y volcado de diagnóstico accidental dentro del contenedor. Un intermediario puede rechazar destinos desconocidos, adjuntar la credencial correcta y mantener el estado de renovación fuera de la memoria del agente.

En macOS, Sallyport sigue este patrón para sus acciones HTTP y SSH compatibles: las credenciales permanecen en su bóveda cifrada y el agente recibe resultados de acciones en lugar de secretos en texto plano. Este diseño resulta útil porque trata la solicitud como el elemento que debe autorizarse, no el archivo de tokens como una comodidad que se entrega.

No coloques archivos de tokens de actualización en directorios de repositorios, espacios de trabajo de CI, carpetas de red compartidas, archivos ocultos del directorio personal, imágenes de contenedores ni rutas de copias de seguridad genéricas. Cada ubicación crea un mecanismo distinto para copiar el archivo y cada copia añade un problema futuro de revocación. Si una herramienta antigua insiste en usar una ruta, dale un directorio de ejecución aislado y de corta duración, propiedad de un asistente de credenciales, y haz que el asistente se encargue de crear y eliminar el archivo. Trátalo como una excepción de compatibilidad con fecha de caducidad, no como el patrón estándar.

## Los alcances deben describir un trabajo, no un departamento

Un agente sin interfaz debe tener alcances que describan su único trabajo. Un token autorizado para leer todos los proyectos porque quizá el agente necesite otro proyecto algún día acabará utilizándose en un contexto que nadie esperaba. Los alcances amplios son populares porque las pantallas de autorización y la documentación de los proveedores pueden resultar frustrantes. El coste llega después, durante un incidente, cuando revocar un token de automatización también interrumpe trabajos sin relación.

Empieza por las llamadas finales a la API, no por la lista de alcances disponibles del proveedor. Anota los verbos y recursos que necesita el trabajo. Un trabajo que obtiene facturas y sube una exportación terminada puede necesitar acceso de lectura a las facturas y acceso de escritura a una ubicación de exportación. No necesita administración de usuarios, eliminación de repositorios, cambios de facturación ni alcances de gestión de permisos porque alguien usó esos permisos durante la configuración inicial.

Los alcances de OAuth por sí solos no bastan. Los permisos del lado de los recursos pueden ampliar el efecto de un alcance que parece modesto. Un token con `files.write` aún puede causar daños en un conjunto grande de recursos si su sujeto tiene acceso a todas las carpetas de los equipos. Vincula la identidad de servicio a un proyecto, carpeta, unidad organizativa o repositorio limitado cuando el proveedor lo permita. Después prueba los casos negativos: una acción contra un recurso de producción cercano debe fallar por un motivo de permisos, no simplemente porque el agente todavía no la haya intentado.

Crea concesiones separadas para funciones separadas aunque el proveedor acepte una lista combinada. Por ejemplo, mantén separado un trabajo de recopilación de datos de solo lectura de otro que publique resultados. Una credencial filtrada que permite publicar tiene un impacto, ritmo de rotación y propietario de aprobación distintos de los de una credencial de lectura. Combinarlas ahorra un flujo de renovación, pero dificulta toda investigación.

Evita los patrones de alcances basados en la sesión de un administrador humano. Los administradores suelen aceptar permisos amplios porque los necesitan para configurar el sistema. El agente en ejecución no hereda el criterio del administrador. Hereda su autorización.

Una prueba útil para la revisión es esta: lee el registro de consentimiento e intenta describir el trabajo en una sola frase. Si la descripción se convierte en «puede gestionar varias cosas que quizá necesitemos», la concesión no está lista. Reduce el trabajo o divídelo. Mantener dos credenciales cuesta menos que descubrir que un agente de exportación podía cambiar la configuración de identidad.

## Los tokens que se renuevan solos necesitan un propietario único

La rotación de tokens de actualización crea un problema de gestión del estado, y los trabajadores desatendidos deben resolverlo deliberadamente. Muchos servidores de autorización rotan los tokens de actualización: tras una renovación correcta, el servidor devuelve un reemplazo y puede invalidar el token anterior. RFC 9700, OAuth 2.0 Security Best Current Practice, recomienda la rotación de tokens de actualización o tokens de actualización vinculados al emisor para que los clientes públicos detecten reproducciones. Es una recomendación de seguridad sólida, pero no hace seguro un archivo compartido.

Piensa en un fallo habitual. El trabajador A y el trabajador B parten del mismo `auth.json` montado. El trabajador A renueva primero y recibe `R2`; el proveedor invalida `R1`. Antes de que A escriba `R2`, el proceso muere o la escritura del sistema de archivos queda en una capa local que B no puede ver. El trabajador B envía `R1`, recibe `invalid_grant` y vuelve a intentarlo. Un operador ve un trabajo fallido, copia una caché antigua desde una copia de seguridad y, con ello, la respuesta al incidente crea más copias de la credencial.

Usa una de estas disposiciones:

1. Un único intermediario de credenciales gestiona las renovaciones y almacena el reemplazo de forma transaccional.
2. Un único trabajador programado es propietario de una concesión concreta, con un bloqueo explícito y sin réplicas paralelas que compartan el estado del token.
3. Existen concesiones separadas para trabajadores separados, de modo que cada token de actualización tiene un único escritor.

La primera disposición suele ser la más limpia. La segunda puede funcionar para un trabajo pequeño y controlado, pero el vencimiento del bloqueo y la recuperación tras fallos requieren un diseño real. La tercera exige más trabajo de consentimiento y ciclo de vida, pero contiene bien los fallos.

No resuelvas la carrera desactivando la rotación si el proveedor lo permite. Esa recomendación resulta atractiva porque oculta el error de concurrencia. También da a un token de actualización robado más tiempo para actuar sin ser detectado. Corrige el modelo de propiedad.

La ruta de persistencia debe actualizar el token nuevo de forma atómica y conservar suficientes metadatos para detectar a un escritor obsoleto. Como mínimo, guarda una versión, la hora de la última renovación correcta y un identificador estable de credencial que sea seguro registrar. El almacén de secretos debe rechazar una actualización que intente sustituir la versión 14 cuando ya exista la versión 15. Una sobrescritura simple permite que un trabajador lento resucite un estado obsoleto.

Cuando el servidor de autorización ofrezca tokens vinculados al emisor, entiende qué queda vinculado. Un mecanismo de prueba puede hacer que un token copiado resulte menos útil sin la clave correspondiente que conserva el cliente. No sustituye el control de acceso alrededor de esa clave ni convierte una concesión de consentimiento humano en una identidad de servicio adecuada. Trátalo como otra barrera, no como una razón para distribuir archivos de caché.

## La rotación es un procedimiento operativo, no un recordatorio del calendario

Una política de rotación solo es creíble cuando alguien puede ejecutarla sin improvisar. La rotación basada en el calendario tiene su lugar, pero los cambios de propietario, la actividad sospechosa, el compromiso de un host, la exposición de un repositorio y los errores `invalid_grant` inesperados deberían activar la misma secuencia preparada. No esperes a la fecha programada si sospechas que se ha escapado un token copiado.

Un procedimiento operativo funcional tiene cinco acciones:

1. Congela el agente o la ruta del intermediario afectados para que no puedan seguir renovando durante el cambio.
2. Identifica el cliente OAuth, la identidad del recurso, los alcances y la versión de la credencial a partir del registro de propiedad y los logs.
3. Revoca el token de actualización o la concesión en el servidor de autorización, usando la consola del proveedor o su endpoint de revocación compatible con RFC 7009 cuando esté disponible.
4. Elimina todas las copias conocidas en ejecución e invalida cualquier proceso de copia de seguridad o caché que pueda restaurarlo.
5. Vuelve a registrar la identidad dedicada, prueba la acción mínima permitida y registra la versión de reemplazo.

RFC 7009 define la revocación de tokens y permite deliberadamente que los servidores revoquen tokens y concesiones relacionados al gestionar una solicitud. Por eso el operador debe conocer el alcance del impacto antes de pulsar el botón de revocación. Un proveedor puede invalidar el token de acceso actual, la familia de tokens de actualización o la concesión completa. La respuesta correcta no es evitar la revocación. Es documentar qué trabajos comparten una concesión para que no la compartan por accidente.

Prueba la rotación con una identidad desechable de un entorno que no sea producción. Confirma que un reemplazo recién emitido funciona, que el token antiguo falla y que un trabajador obsoleto no puede sobrescribir el estado nuevo. Después practica la respuesta ante un token revocado. Quieres que el trabajo falle de forma segura, con un error reconocible y una identidad que pueda convertirse en ticket, no que recurra silenciosamente a la sesión almacenada de un desarrollador.

Las copias de seguridad necesitan un tratamiento especial. Las copias cifradas siguen conservando un token de actualización hasta que termina el periodo de retención. Puede que no puedas eliminar de inmediato los bloques históricos, pero sí puedes revocar de inmediato la concesión expuesta. Documenta la ubicación de retención para que un investigador sepa que el material de recuperación contiene un secreto obsoleto, incluso cuando ya no funcione.

## Audita por separado las acciones y los eventos de renovación

Los registros de auditoría deben mostrar tanto los eventos de renovación como las acciones realizadas con los tokens de acceso resultantes. Un evento de renovación indica que una credencial siguió activa. No indica si el agente leyó un informe o modificó mil registros. A la inversa, un registro de acción de API sin una versión de credencial no permite saber qué ruta de renovación la autorizó.

Registra metadatos seguros para cada renovación: fecha y hora, identificador de credencial, versión del token antes y después, identificador del cliente OAuth, identificador del sujeto, alcance solicitado o devuelto si el proveedor lo expone, host de ejecución o identidad del intermediario y resultado. Registra metadatos seguros para cada acción protegida: identificador de sesión del agente o del trabajo, destino solicitado, operación, identificador del recurso, decisión de autorización, código de resultado e identificador de correlación.

No registres nunca el token de actualización, el token de acceso, el código de autorización, el secreto de cliente, la URL de callback completa ni la cabecera Authorization sin procesar. Redactar los datos después de registrarlos llega demasiado tarde si un recopilador, una grabadora de terminal o un monitor de errores ya recibió el evento. Diseña llamadas de registro que nunca acepten esos campos en lugar de confiar en que cada persona que llama recuerde aplicar un filtro.

Una consulta útil para un incidente empieza con una acción sobre un recurso y retrocede por la cadena. Supón que una exportación apareció en el destino equivocado. Debes poder responder: qué trabajo la solicitó, qué proceso ejecutó el trabajo, qué cliente OAuth utilizó, qué versión de credencial proporcionó el acceso, cuándo se emitió esa versión y si otro host utilizó la misma versión. Si algún vínculo depende de leer el valor del token, el diseño de auditoría está roto.

La evidencia de manipulación importa cuando los agentes actúan sin supervisión constante. Un registro de solo adición en el mismo host es mejor que el silencio, pero un atacante que controla el host puede editar tanto la caché como el registro. Conserva los datos de auditoría en un sistema protegido y verifica su integridad de forma independiente. En los sistemas capaces de conservar un registro cifrado y encadenado mediante hashes, la verificación sin conexión permite a un investigador comprobar si las entradas cambiaron sin exponer primero los secretos subyacentes.

## La aprobación debe recaer en las acciones, no en la exposición del token

La aprobación humana resulta más útil en el límite donde un agente intenta afectar a un sistema externo. Pedir a una persona que apruebe una vez un archivo de token de actualización y permitir después que cualquier proceso lo use durante semanas crea una apariencia de control mientras pone la cadena sensible en circulación.

Elige las aprobaciones según las consecuencias. Una consulta de solo lectura puede ejecutarse con una sesión preaprobada y de alcance limitado. Enviar datos a un destino nuevo, modificar permisos, eliminar un recurso o usar una credencial fuera de su trabajo habitual debe detenerse para que una persona decida. El aprobador debe ver el proceso solicitante, el destino, la operación y suficientes parámetros para entender el efecto. Un aviso genérico de «permitir OAuth» es casi inútil.

No confundas los avisos frecuentes con seguridad. Si cada llamada inofensiva pide consentimiento, la gente aprobará por costumbre. Establece un límite de sesión razonable para el trabajo rutinario y exige después una aprobación independiente para las operaciones de alto impacto. La decisión debe seguir siendo visible cuando el agente se ejecute en una mesa de cocina, con una conexión de viaje o dentro de un trabajo nocturno.

La prueba es sencilla: si una instrucción del agente se vuelve hostil o un complemento se comporta mal, ¿puede convertir el acceso en una acción en el mundo exterior sin atravesar un control que muestre a una persona lo que va a ocurrir? Si la respuesta es sí porque ya tiene `auth.json`, coloca la credencial detrás de un intermediario y rediseña la superficie de solicitudes.

## Trata los archivos auth.json antiguos como un proyecto de migración

Las cachés de tokens existentes rara vez desaparecen en una tarde, pero dejarlas sin documentar porque migrarlas resulta incómodo garantiza que se vuelvan permanentes. Empieza por encontrar a cada consumidor y después clasifica el archivo por servicio, sujeto, alcances, entorno, número de escritores y ruta de almacenamiento. Revoca las copias que no puedas atribuir. Una credencial cuyo propietario se desconoce no tiene por qué renovarse.

Mueve un flujo de trabajo cada vez. Primero crea una identidad de recurso y un cliente dedicados. Después coloca su token de actualización detrás del almacén de secretos o del intermediario elegido. A continuación cambia el trabajo para que envíe una solicitud de acción permitida y compara el nuevo registro de auditoría con el resultado del trabajo anterior. Solo cuando el reemplazo funcione debes revocar la concesión personal antigua.

Espera que algunas herramientas se resistan. Algunos SDK dan por hecho que son propietarios de una caché JSON local y renuevan en silencio cuando la encuentran. Mantén esas herramientas en un envoltorio de compatibilidad restringido, con un único proceso autorizado a leer el archivo y sin acceso general para el agente. Incluye la eliminación de ese envoltorio en la lista de trabajo del propietario del servicio. «La biblioteca lo necesita» explica una excepción temporal, pero no justifica una vía permanente de filtración de secretos.

El primer objetivo de la migración debe ser el archivo con el alcance más amplio o el propietario menos claro, no el archivo más fácil de mover. Esas son las credenciales que convierten un error contenido del agente en un incidente de producción. Cuando hayas migrado un flujo de forma limpia, haz que el patrón antiguo sea difícil de repetir mediante revisiones de despliegue, cambios en las plantillas y la negativa a montar cachés de credenciales sin procesar en los entornos de ejecución de los agentes.

Un token de actualización debe tener un único propietario responsable, una única ruta de renovación controlada y un registro de auditoría que nombre cada acción externa que autorizó. Si tu `auth.json` actual no cumple esas condiciones, revócalo después de demostrar que la ruta de reemplazo funciona.
