MCP Fusion/Security and governance/Autenticación
Autenticación
Tres paquetes de autenticación para conectores: verificación de JWT con JWKS, claves de API con comparación segura en tiempo y el flujo de autorización de dispositivo OAuth 2.0 convertido en herramientas que el agente puede manejar.
Un conector que actúa sobre la cuenta de alguien debe saber quién está haciendo la solicitud. MCP Fusion incluye tres paquetes de autenticación, cada uno con un middleware y una herramienta de autenticación opcional, para que el agente pueda ser bloqueado, desafiado y después desbloqueado sin que tu handler note la diferencia.
De dónde viene la identidad
La autenticación lee la identidad de ctx, y ctx se crea por solicitud mediante contextFactory. La configuración canónica:
registry.attachToServer(server, {
contextFactory: async (extra) => ({
token: extra.session?.authToken ?? '',
headers: extra.headers ?? {},
}),
});Todo lo que sigue lee ese contexto.
JWT
npm install @mcpfusion/jwtimport { requireJwt } from '@mcpfusion/jwt';
f.query('billing.list_invoices')
.use(requireJwt({
jwksUri: 'https://auth.example.com/.well-known/jwks.json',
issuer: 'https://auth.example.com/',
audience: 'my-connector',
requiredClaims: ['sub', 'tenant_id'],
onVerified: (ctx, payload) => {
ctx.tenantId = payload.tenant_id; // derived identity for the handler
},
}))
.handle(async (input, ctx) => listInvoices(ctx.tenantId));JwtVerifier acepta secret (HS256), publicKey (PEM) o jwksUri (conjunto de claves remoto, almacenado en caché por verificador). Con jose instalado funcionan RS256, ES256 y JWKS; sin él, una ruta nativa HS256 verifica con timingSafeEqual y rechaza cualquier otro algoritmo. issuer, audience, clockTolerance (60 segundos) y requiredClaims se validan en cada token. verifyDetailed() devuelve { valid, payload, reason } cuando quieres el motivo en lugar de null.
Orden predeterminado para extraer el token: ctx.token, después ctx.jwt, después ctx.headers.authorization (se elimina el prefijo Bearer ). Los fallos devuelven un toolError autocurable con el código JWT_INVALID y una acción auth para recuperarse.
El paquete JWT verifica tokens, pero no los renueva. El código fuente no admite refresh tokens, así que un conector que necesite acceso duradero al proveedor debe usar el flujo OAuth de abajo o el almacén de credenciales.
La herramienta opcional createJwtAuthTool() expone verify y status como acciones que el agente puede invocar cuando el propio cliente tiene el token.
Claves de API
npm install @mcpfusion/api-keyimport { requireApiKey } from '@mcpfusion/api-key';
f.mutation('billing.refund')
.use(requireApiKey({
keys: [process.env.SERVICE_KEY!],
onValidated: (ctx) => { ctx.service = 'billing-service'; },
}))
.handle(...);Las claves pueden ser texto plano, con hash interno mediante SHA-256 al construirlas, o estar prehasheadas, o pueden validarse con tu función asíncrona validator. El orden de comprobación es: no vacía, minLength (16 por defecto), prefix opcional y después el validador o el conjunto de hashes. El orden de extracción es: ctx.apiKey, ctx.headers['x-api-key'] y luego ctx.headers.authorization (se eliminan los prefijos ApiKey y Bearer ).
La comparación busca ser constante en el tiempo: el gestor compara los hashes de forma que no se detiene en el primer byte diferente. No trates la longitud de la clave como un secreto.
Flujo de dispositivo OAuth para el agente
Cuando el conector necesita una cuenta que el agente aún no tiene, el flujo debe poder conducirse desde un chat: el servidor entrega un código y una URL, la persona aprueba en un navegador y el agente vuelve a preguntar. Es RFC 8628, y el paquete lo convierte en herramientas:
npm install @mcpfusion/oauthimport { createAuthTool, requireAuth } from '@mcpfusion/oauth';
const auth = createAuthTool({
clientId: process.env.OAUTH_CLIENT_ID!,
authorizationEndpoint: 'https://auth.example.com/device/code',
tokenEndpoint: 'https://auth.example.com/device/token',
onAuthenticated: (token) => { /* cache or forward the token */ },
});
f.query('analytics.report')
.use(requireAuth()) // blocks with AUTH_REQUIRED until a token exists
.handle(...);La herramienta expone cuatro acciones:
| Action | Behavior |
|---|---|
login | solicita un código de dispositivo y devuelve la URL de verificación y el código |
complete | intercambia el código una vez; authorization_pending significa "todavía no, pregunta otra vez" |
status | informa de si existe un token y, opcionalmente, a qué usuario pertenece |
logout | elimina el token |
El bucle de sondeo respeta RFC 8628: el primer sondeo es inmediato, authorization_pending continúa, slow_down añade cinco segundos, cualquier otro error termina con la descripción del proveedor y el plazo lanza "Device authorization expired. Start a new flow." El verificador no envía un scope por ti y no hay renovación automática: el almacén de tokens es un archivo bajo el directorio personal (.mcpfusion/token.json, modo 0600, con un fallback de icacls en Windows), así que considéralo el valor predeterminado local para un solo usuario y configura tu propia persistencia para un conector alojado.
requireAuth() comprueba la presencia de un token, no su validez. Combínalo con requireJwt cuando el token upstream deba verificarse criptográficamente.
Notas para producción
- Prefiere credenciales de plataforma a tokens de usuario para llamadas entre servidores: decláralas con
defineCredentialsy léelas conrequireCredential. Consulta Credentials. - En Vinkius Cloud, invoca con un token de conexión y usa Connection Tokens en la consola para revocar el acceso por cliente.
- El middleware de autenticación se combina con el resto de la cadena: colócalo en el exterior para que las llamadas no autorizadas nunca lleguen a la validación, como se muestra en Middleware and context.
Próximos pasos
- Multi-tenant connectors: la identidad se convierte en aislamiento
- Security pipeline: dónde se sitúa la autenticación entre las capas
- Credentials: secretos del servidor sin tokens de usuario
