¿Por qué no bloquear simplemente a los agentes en las acciones sensibles?
Algunas acciones de su aplicación importan más que otras. Cambiar una contraseña, añadir un miembro al equipo, exportar datos, eliminar un proyecto, aprobar un pedido: si cualquiera de estas acciones ocurre sin la autoridad adecuada, el daño es real.
Al mismo tiempo, cada vez más del trabajo legítimo en su app lo realiza la automatización. Un usuario pide a un asistente que actualice sus ajustes. Una integración de un socio crea registros según un calendario. Un agente interno genera tickets de soporte. Bloquear a todos los clientes automatizados en las rutas sensibles rompe ese trabajo y empuja a las personas de vuelta al esfuerzo manual o a soluciones provisionales más difíciles de proteger.
La respuesta no es "bloquear agentes" ni "confiar en los agentes". Es un modelo en el que el riesgo de la acción, la autoridad detrás de la solicitud y la evidencia sobre el actor cumplen cada uno un papel distinto. Esta guía construye ese modelo. Para una visión más amplia, vea diseñar políticas a nivel de app para humanos y agentes de IA.
Paso 1: clasifique sus rutas por riesgo
Empiece clasificando acciones, no clientes. Un esquema sencillo de tres niveles funciona para la mayoría de las aplicaciones:
| Nivel | Ejemplos | Requisito por defecto |
|---|---|---|
| Bajo | Leer datos públicos, buscar, ver el panel propio | Autenticación normal, si la hay |
| Medio | Crear o editar contenido propio, invitar a un espectador | Autenticado, autorizado para el recurso |
| Alto | Cambiar credenciales, cambiar la titularidad, exportar en masa, eliminar, aprobar | Autorizado más verificación de refuerzo o revisión |
Escriba el nivel en la configuración de la ruta para que quede visible en la revisión de código:
type Tier = "low" | "medium" | "high";
export const routeTier: Record<string, Tier> = {
"GET /projects": "low",
"POST /projects": "medium",
"POST /projects/:id/members": "medium",
"POST /account/password": "high",
"POST /exports": "high",
"DELETE /projects/:id": "high",
};Los niveles cambian despacio y son fáciles de razonar. Todo lo demás de esta guía depende de ellos.
Paso 2: ¿En qué se diferencian identidad, credenciales y autorización?
A menudo se confunden tres preguntas:
- ¿Quién o qué está actuando? Esto es evidencia del actor: una persona interactiva, una persona con asistencia de IA, un agente o Unknown, con una base como Verified o Declared.
- ¿Qué credencial se presentó? Una cookie de sesión, una clave de API, un token de acceso OAuth.
- ¿Se permite que esta credencial haga esta acción sobre este recurso? Esto es autorización.
Una firma de agente verificada (RFC 9421) responde bien a la primera pregunta. No dice nada sobre la tercera, un punto que se trata en detalle en qué demuestran las solicitudes firmadas de agentes de IA y qué no. Un token OAuth con el ámbito correcto responde a la tercera. Dice poco sobre la primera. Su decisión para una acción de nivel alto necesita siempre una buena respuesta a la tercera pregunta, y usa la primera para decidir cuánta garantía adicional pedir.
interface Context {
actor: { actor: "human" | "human_ai" | "agent" | "unknown"; basis: "verified" | "declared" | "inferred" | "unknown" };
credential: { type: "session" | "oauth" | "api_key"; scopes: string[]; subject: string };
}
function authorized(ctx: Context, action: string, resourceOwner: string): boolean {
return ctx.credential.subject === resourceOwner && ctx.credential.scopes.includes(action);
}La autorización nunca se relaja por un resultado favorable del actor. El contexto del actor solo añade requisitos o elige entre rutas igualmente seguras.
Paso 3: use autoridad delegada para agentes que actúan por personas
Cuando un agente actúa en nombre de un usuario, dele su propia credencial con autoridad limitada en lugar de permitirle reutilizar la sesión del usuario. OAuth 2.0 es la herramienta estándar: el usuario aprueba ámbitos específicos para un cliente específico, y el token registra ese cliente. RFC 9700, la OAuth 2.0 Security Best Current Practice, describe cómo desplegarlo de forma segura. Los servidores MCP siguen el mismo patrón: la especificación de autorización de MCP trata un servidor MCP protegido como un resource server de OAuth 2.1. Nuestra publicación ¿quién llama a su MCP server? aplica esto a las llamadas a herramientas.
Esto produce exactamente lo que necesita para las acciones sensibles:
- El token le indica qué cliente está actuando y para quién.
- Los ámbitos limitan lo que puede hacer. Un agente de programación con
calendar:writeno puede cambiar una contraseña. - El usuario puede revocar la concesión sin cambiar sus propias credenciales, y OAuth 2.0 Token Revocation (RFC 7009) define cómo un cliente indica al authorization server que un token ya no debe ser válido.
- Los registros de auditoría muestran que el agente, no el usuario, realizó la acción.
Si su app aún no admite credenciales delegadas, priorícelo para las acciones que los agentes necesitan con más frecuencia. Es el control más eficaz para el acceso automatizado.
Paso 4: ¿cuándo debe pedir una verificación de refuerzo?
Verificación de refuerzo significa pedir garantía adicional en el momento de una acción sensible. Para APIs protegidas por OAuth, RFC 9470 define cómo un resource server indica a un cliente que la autenticación del token actual no es lo bastante fuerte ni reciente. La verificación de refuerzo adecuada depende de quién actúe:
- Persona interactiva (Human, Human + AI): reautenticación (véanse los requisitos de reautenticación en NIST SP 800-63B), un aviso de passkey basado en WebAuthn o un código de un solo uso.
- Agente con credencial delegada: un ámbito dedicado a la acción de nivel alto, concedido explícitamente por el usuario, o una confirmación enviada al usuario por un canal externo.
- Unknown: la verificación fuerte existente de la ruta, sin cambios.
type Requirement = "none" | "reauth" | "explicit_scope" | "user_confirmation" | "review";
function stepUp(tier: Tier, ctx: Context): Requirement {
if (tier !== "high") return "none";
const { actor } = ctx.actor;
if (actor === "human" || actor === "human_ai") return "reauth";
if (actor === "agent" && ctx.credential.type === "oauth") return "explicit_scope";
if (actor === "agent") return "user_confirmation";
return "reauth";
}Observe que un resultado Human no omite la verificación de refuerzo. Selecciona la verificación de refuerzo que corresponde a una persona interactiva. Las inferencias pueden ser erróneas, así que deben cambiar la forma de la comprobación, no eliminarla.
Paso 5: dirija a revisión humana cuando haga falta criterio
Algunas acciones son poco frecuentes, de alto impacto y difíciles de automatizar con seguridad: exportaciones masivas de datos de clientes, recuperación de cuentas tras perder credenciales o eliminación de una organización. Para estas, una cola de revisión suele ser mejor que cualquier regla automática.
El contexto del actor hace la revisión más rápida y más justa al dar al revisor la evidencia: la clase, la base, la credencial utilizada, el historial de solicitudes similares. El revisor decide. La clasificación informa.
function shouldReview(route: string, ctx: Context): boolean {
const reviewRoutes = new Set(["POST /exports", "POST /account/recover"]);
if (!reviewRoutes.has(route)) return false;
return !(ctx.credential.type === "oauth" && ctx.credential.scopes.includes("export:bulk"));
}Paso 6: elija el comportamiento ante fallos por nivel
La evaluación del actor puede agotarse por tiempo o carecer de evidencia. Decida de antemano qué ocurrirá.
- Nivel bajo: fail open. La solicitud continúa con normalidad.
- Nivel medio: fail open, con la autorización normal en su sitio.
- Nivel alto: fail closed hacia la verificación fuerte existente. La evidencia del actor ausente nunca debilita la protección, y nunca bloquea una solicitud que de otro modo habría superado sus comprobaciones normales.
La propiedad clave es la simetría. Un fallo en la evaluación del actor debe dejar la acción exactamente tan segura, y exactamente tan disponible, como estaba antes de añadir el contexto del actor.
Paso 7: no tome decisiones con consecuencias sobre personas a partir de inferencias
Una clasificación inferida es evidencia sobre una interacción, no un hecho sobre una persona. No niegue a alguien una solicitud de empleo, una decisión de crédito, un resultado de examen, una vivienda o el acceso a un servicio esencial porque una sesión pareciera automatizada o asistida por IA. En esos flujos, use el contexto del actor para elegir un proceso, como revisión humana o una ruta alternativa de verificación, y asegúrese de que la persona pueda completarlo.
Esto es tanto un principio de equidad como una medida práctica. Las inferencias tienen falsos positivos, y el coste de un falso positivo en estos flujos recae sobre alguien que no hizo nada mal.
Paso 8: despliegue primero con observación
Antes de que nada de esto afecte a solicitudes reales, ejecútelo en modo observación y vista previa:
- Registre el nivel, la clase de actor, la base, el tipo de credencial y la verificación de refuerzo que su política requeriría.
- Revise muestras de solicitudes de nivel alto por clase. ¿Los agentes legítimos usan credenciales delegadas o reutilizan sesiones de usuario?
- Corrija los huecos que encuentre, a menudo ofreciendo credenciales con ámbitos limitados, antes de aplicar la enforcement.
- Aplique la enforcement a una pequeña parte de una sola ruta, mida las tasas de finalización y luego amplíe.
Paso 9: mantenga una traza de auditoría que responda "quién y en nombre de quién"
Para cada acción de nivel alto, registre lo suficiente para reconstruir lo ocurrido después:
- la clase y la base del actor en el momento de la solicitud,
- el tipo de credencial, el cliente al que se emitió y el sujeto que representa (OAuth 2.0 Token Exchange, RFC 8693, define una claim
actpara registrar exactamente este tipo de relación de "actuando en nombre de"), - los ámbitos que autorizaron la acción,
- la exigencia de verificación de refuerzo o revisión aplicada y su resultado.
audit.write({
action: "project.export",
actor: ctx.actor,
client: ctx.credential.type === "oauth" ? clientIdFromToken(req) : undefined,
subject: ctx.credential.subject,
scopes: ctx.credential.scopes,
requirement,
outcome: "approved",
at: new Date().toISOString(),
});Con esta traza, una pregunta como "¿la eliminó una persona o un asistente, y quién la aprobó?" tiene una respuesta clara. Eso hace más rápida la respuesta a incidentes y da a los usuarios confianza en que la ayuda automatizada en su app es responsable.
Un ejemplo práctico
Una app de gestión de proyectos ve a un asistente actualizar fechas de vencimiento de tareas para usuarios y, ocasionalmente, intentar exportar proyectos completos.
- Actualizar una tarea es nivel medio. El asistente usa un token OAuth con
tasks:write. Autorizado, sin verificación de refuerzo. Permitido. - Exportar un proyecto es nivel alto. El token del asistente no tiene
export:bulk. La app envía al usuario una solicitud de confirmación. El usuario aprueba y la app concede el ámbito para ese cliente. - Un cliente Unknown intenta la misma exportación con una cookie de sesión reutilizada. Se aplica el aviso de reautenticación existente, exactamente igual que antes.
Nadie fue bloqueado por ser un agente. Toda acción de alto impacto llevó autoridad explícita.
Dónde encaja Proof of Actor
Proof of Actor aporta la parte del actor de este modelo: quién o qué está actuando y sobre qué base. Su aplicación conserva la autenticación, la autorización y la decisión final. Detecte el actor, Understand cómo usa cada clase sus rutas sensibles y Route cada solicitud al nivel adecuado de garantía.
Para diseñarlo para su aplicación con nuestro equipo, solicite acceso anticipado. Para escenarios de SaaS con más detalle, vea SaaS Apps & Websites.
Fuentes
- RFC 6749: The OAuth 2.0 Authorization Framework: credenciales delegadas y con ámbitos para clientes
- RFC 9700: Best Current Practice for OAuth 2.0 Security: orientación actual de seguridad para despliegues OAuth
- RFC 7009: OAuth 2.0 Token Revocation: revocar una concesión sin cambiar las credenciales del usuario
- RFC 9470: OAuth 2.0 Step Up Authentication Challenge Protocol: indicar que se requiere una autenticación más fuerte o más reciente
- RFC 8693: OAuth 2.0 Token Exchange: la claim
act(actor) para la delegación - MCP specification 2026-07-28: Authorization: servidores MCP como resource servers de OAuth 2.1
- NIST SP 800-63B: Authentication and Authenticator Management: guía de reautenticación
- W3C Web Authentication (WebAuthn) Level 3: el estándar detrás de los avisos de passkey
- RFC 9421: HTTP Message Signatures: lo que establece una firma de agente verificada