# OAuth y tokens

> Qué pide la pantalla de permiso de OAuth, dónde aparece la conexión y cómo se revoca, roles y ámbitos de los tokens de API, y el perfil ligero.

El servidor MCP acepta dos tipos de credencial, y las dos son tokens de la organización con un rol: una **conexión OAuth**, que se crea cuando das permiso desde el cliente, y un **token de API** que creas tú. En los dos casos el asistente nunca puede hacer más que tú.

## Conectar con OAuth

El servidor implementa la [autorización de MCP](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) (OAuth 2.1). `mcp.openwaf.dev` es el recurso protegido y `dash.openwaf.dev`, donde inicias sesión, el servidor de autorización. Desde tu lado:

1. Le das al cliente solo la URL `https://mcp.openwaf.dev/mcp`.
2. El cliente se registra solo y abre `dash.openwaf.dev` en el navegador. Si no tienes sesión, inicias sesión y vuelves a la misma petición.
3. La **pantalla de permiso** enseña el nombre del cliente (lo declara el propio cliente, así que se marca como no verificado) y el host al que se le devolverá, y te pide elegir:
   - **Organización:** una de las tuyas. Las organizaciones suspendidas o pendientes de aprobación no se pueden elegir.
   - **Rol:** solo lectura (`readonly`), técnico (`tech`) o administrador (`admin`), nunca por encima del tuyo. Un miembro limitado a un cliente puede elegir `readonly` o `tech`.
   - **Caducidad:** 7, 30 o 90 días.
4. Permites o deniegas. Denegar le devuelve `access_denied` al cliente.


Si la dirección de vuelta del cliente no es una de las que registró, el panel muestra el error y **no redirige** a ningún sitio. Los demás errores se muestran con un botón «Volver a la aplicación» y el host de destino, nunca con una redirección automática.

## Dónde aparece la conexión

La conexión es un token de la organización: aparece en **Tokens de API** como «MCP · <cliente>», con la insignia «App OAuth», el rol y la caducidad que elegiste. Como cualquier token, su rol nunca supera el actual del miembro y muere si el miembro sale de la organización.

**Para quitar el acceso**, revócalo en **Tokens de API**: sus tokens de acceso y de refresco dejan de valer en el acto. El cliente también puede revocarlo él mismo.

Por debajo, el cliente guarda un token de acceso de 1 hora (`owfa_…`) y uno de refresco de un solo uso (`owfr_…`); de cada secreto solo se guarda su SHA-256. Un token de acceso OAuth solo abre el endpoint MCP: el resto de la API REST responde 401.

En la auditoría quedan `oauth.authorize` (permiso dado, con cliente, host de vuelta, rol y caducidad), `token.create` y `token.revoke`.

## Tokens de API

Para clientes sin OAuth, o para automatizar, crea un token propio para el asistente en el panel (**Tokens de API**) o con `POST /v1/orgs/{org}/tokens`, con el rol justo y caducidad:

| Elección | Efecto |
|---|---|
| `readonly` | El asistente solo ve las herramientas de lectura; las de escritura ni aparecen en `tools/list` |
| `tech` | Lectura y escritura de zonas, registros, ajustes de borde y reglas |
| `admin` | Todo, también las herramientas de escritura de egress y `audit_log` |
| Limitado a un cliente (`client_id`) | El asistente solo ve las zonas de ese cliente |
| Limitado a una zona (`zone_id`) | El asistente solo ve esa zona |

`audit_log` necesita `admin`, o `tech` limitado a un cliente. Las zonas fuera del ámbito del token responden `not_found`, como si no existieran. Los tokens `owf_…` funcionan igual en todas las URL del servidor.

> **Atención: Un token es una credencial**
>
> Va en la configuración del cliente MCP, nunca en la conversación.


## Perfil ligero

La lista completa de herramientas ocupa unos 54 KB de `tools/list` (unos 12 500 tokens) que se cargan en cada conversación. El perfil `lite` solo lista el descubrimiento, un modo código y las lecturas de cada día (unos 1300 tokens):

| Herramienta | Para qué |
|---|---|
| `search_tools` | Busca herramientas y operaciones de la API por palabras (en español o en inglés) |
| `describe_tool` | El esquema de entrada completo de una herramienta u operación de la API, un ejemplo y, si escribe, el protocolo simular → confirmar |
| `call_tool` | Llama a cualquier herramienta por su nombre, para los clientes que solo llaman a herramientas listadas |
| `execute` | Modo código: un script de JavaScript de solo lectura que se ejecuta en el servidor con los permisos del token; puede simular escrituras pero nunca aplicarlas |
| `list_zones`, `get_zone`, `list_records` | Las lecturas de cada día |

Todas las demás herramientas **siguen existiendo** y se llaman por su nombre o con `call_tool`, con los mismos permisos. Se elige con el parámetro `profile` de la URL o con la cabecera `X-OpenWAF-MCP-Profile: lite`; un valor desconocido responde 400. **Sin parámetro, el perfil es `full`**, así que los clientes ya configurados no cambian.

**Claude Code**

```sh
claude mcp add --transport http openwaf-lite 'https://mcp.openwaf.dev/mcp?profile=lite' \
  --header "Authorization: Bearer $OPENWAF_TOKEN"
```
**Cursor**

```json
{ "mcpServers": { "openwaf": { "type": "http", "url": "https://mcp.openwaf.dev/mcp?profile=lite",
  "headers": { "Authorization": "Bearer owf_…" } } } }
```
