---
title: "Conéctate con OAuth"
description: "Autoriza clientes MCP y la CLI de ThunderPhone sin compartir una clave de API."
---

OAuth permite que una aplicación se conecte a una organización de ThunderPhone con los permisos que apruebes. Los clientes de directorio deben usar OAuth de forma predeterminada. Las claves de API de organización siguen disponibles para clientes que requieren un token Bearer configurado manualmente.

## Aprobar una conexión

Inicia la conexión en tu cliente MCP. Inicia sesión en ThunderPhone, verifica el nombre de la aplicación y los permisos solicitados, elige una organización y selecciona **Aprobar**. Selecciona **Denegar** si no iniciaste la conexión o no confías en la aplicación. Los nombres de las aplicaciones los proporcionan sus desarrolladores y no son una insignia de verificación.

Los permisos de lectura exponen los datos indicados, incluidas las grabaciones y transcripciones cuando se solicita `calls:read`. Los permisos de escritura pueden modificar o eliminar recursos; las llamadas, campañas, compras de números telefónicos y despliegues pueden generar costos o afectar la producción. Tu rol en la organización sigue aplicándose.

Para una conexión mediante CLI, abre el enlace de verificación que aparece en tu terminal, compara el código de ocho caracteres, selecciona tu organización y aprueba. Abrir el enlace por sí solo no otorga acceso. Los códigos vencen después de 15 minutos.

## Desconectar una aplicación

Abre **Organización → Claves de API → Aplicaciones autorizadas** en el panel y selecciona **Revocar**. Esto revoca la autorización que seleccionaste para la organización actual, incluidos sus tokens de acceso y actualización. Vuelve a conectarte desde la aplicación si quieres autorizarla nuevamente.

## Descubrimiento para clientes MCP

Use la URL del servidor `https://api.thunderphone.com/v1/mcp`. Una solicitud sin autenticación válida recibe `401` con:

```http
WWW-Authenticate: Bearer resource_metadata="https://api.thunderphone.com/.well-known/oauth-protected-resource"
```

Obtenga ese documento y luego obtenga los metadatos del servidor de autorización en `https://api.thunderphone.com/.well-known/oauth-authorization-server`. Los metadatos del recurso también están disponibles en `/.well-known/oauth-protected-resource/v1/mcp`. Use los endpoints devueltos en lugar de construirlos. El identificador del recurso es `https://api.thunderphone.com/v1/mcp`.

El servidor admite código de autorización con **S256 PKCE**, tokens de actualización rotativos, registro dinámico de clientes públicos, revocación y la concesión de autorización de dispositivo. No hay secretos de cliente ni concesiones implícitas. El descubrimiento de OpenID también está disponible en `/.well-known/openid-configuration`; incluye los mismos campos del servidor de autorización, además de `subject_types_supported: ["public"]` y el endpoint de información del usuario. No se admiten tokens de ID ni Documentos de Metadatos de ID de Cliente (CIMD).

### Registre un cliente público

Envíe JSON a `POST /v1/oauth/register`:

```json
{
  "client_name": "My MCP client",
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

Guarde el `client_id` devuelto. Las redirecciones deben usar HTTPS, o HTTP en `127.0.0.1` o `localhost`. Registre la URI de devolución de llamada exacta, incluidos el puerto y la ruta. Se rechazan los fragmentos y las credenciales incorporadas. Los valores opcionales `client_uri` y `logo_uri` deben usar HTTPS; ThunderPhone no los obtiene durante el registro. El registro tiene límite de solicitudes. Los clientes registrados no vencen y permanecen registrados cuando se revoca una conexión. Las devoluciones de llamada HTTPS incluyen `https://chatgpt.com/connector/oauth/<id>` y `https://chatgpt.com/connector_platform_oauth_redirect`. Cada conexión puede registrar su propio cliente.

### Código de autorización

Abra el endpoint de autorización detectado con `client_id`, el `redirect_uri` registrado exacto, `response_type=code`, un `state` aleatorio, `scope`, `code_challenge`, `code_challenge_method=S256` y `resource=https://api.thunderphone.com/v1/mcp`. Calcule el desafío como el resumen SHA-256 base64url sin relleno de un verificador PKCE nuevo y de alta entropía. Verifique el `state` y `iss` devueltos antes de intercambiar el código. Cada respuesta de autorización, incluidos el rechazo y los errores de protocolo, identifica al emisor con `iss`, que coincide exactamente con el `issuer` detectado. Los errores por un cliente o una devolución de llamada no válidos se devuelven localmente sin redirigir a esa devolución de llamada.

Intercambie en `POST /v1/oauth/token` mediante codificación de formulario (también se acepta JSON):

```text
grant_type=authorization_code
client_id=<your client id>
code=<single-use authorization code>
redirect_uri=<exact registered redirect URI>
code_verifier=<original PKCE verifier>
resource=https://api.thunderphone.com/v1/mcp
```

El parámetro opcional `resource` se acepta tanto en solicitudes de autorización como de token, incluidos los intercambios de actualización y dispositivo. Cuando se omite, toma como valor predeterminado el recurso MCP detectado. Cuando está presente, debe coincidir exactamente con ese recurso; otros valores devuelven `invalid_target`. Los tokens de acceso incluyen esa audiencia, y MCP rechaza los tokens con una audiencia ausente o diferente con `401` y un desafío de descubrimiento.

Las solicitudes de autorización y los códigos vencen después de 10 minutos. Cada respuesta de token contiene `access_token`, `token_type` (`Bearer`), `expires_in` (3600 segundos de forma predeterminada), `refresh_token`, `scope`, `organization_id` y `organization_name`. Envíe los tokens de acceso únicamente mediante el encabezado `Authorization: Bearer`. Nunca coloque tokens en URL, registros, control de versiones ni chat.

### Actualice y revoque

Actualice con `grant_type=refresh_token`, `client_id`, `refresh_token` y `resource` en el endpoint de token. Guarde el nuevo token de actualización de forma atómica y deje de usar el anterior. Los tokens de actualización vencen después de 30 días sin una actualización exitosa. Un `scope` opcional puede limitar los permisos concedidos. `offline_access` siempre está incluido y siempre se emiten tokens de actualización. Una solicitud inicial sin `scope` concede únicamente `offline_access`, por lo que los clientes deben solicitar los permisos que necesitan.

La reutilización de código y la reutilización de un token de actualización rotativo revocan toda la autorización. Serialice las actualizaciones dentro de un cliente; reproducir una credencial intercambiada correctamente no es una estrategia segura de reintento.

Para desconectar, envíe `token` y `client_id` a `POST /v1/oauth/revoke`. Revocar cualquiera de los tokens revoca su autorización, incluidos todos los tokens emitidos a partir de él. Un token desconocido devuelve éxito sin revelar si existe. Las sesiones del panel pueden enumerar sus propias autorizaciones en `GET /v1/oauth/grants` y revocar una en `DELETE /v1/oauth/grants/<id>`, con `X-ThunderPhone-Org` seleccionando la organización.

### Autorización de dispositivo

La autorización de dispositivo está restringida a clientes prerregistrados; los clientes registrados dinámicamente reciben `unauthorized_client`. El cliente público prerregistrado `thunderphone-cli` admite autorización de dispositivo y actualización. Envíe `client_id=thunderphone-cli` y `scope` a `POST /v1/oauth/device/code`. Muestre `user_code` y `verification_uri` a la persona usuaria, o abra `verification_uri_complete`.

Sondee el endpoint de token con `grant_type=urn:ietf:params:oauth:grant-type:device_code`, `client_id` y `device_code`, esperando al menos el `interval` devuelto (5 segundos). Continúe con `authorization_pending`. En `slow_down`, use el nuevo `interval` devuelto en la respuesta (aumentado en 5 segundos) para cada solicitud posterior. Deténgase con `access_denied`, `expired_token` o cualquier otro error. Nunca apruebe automáticamente un código de dispositivo.

El cliente prerregistrado `thunderphone-mcp` acepta `http://127.0.0.1/callback` y `http://localhost/callback` en cualquier puerto. El esquema, host, ruta y consulta deben coincidir; el intercambio de token debe usar la URI de redirección exacta, incluido el puerto, de la autorización. Los clientes registrados dinámicamente requieren una coincidencia exacta de la URI de redirección, incluido el puerto. Registre dinámicamente una devolución de llamada distinta si necesita otra ruta.

### Identidad de la cuenta y verificaciones de dominio del espacio de trabajo

Solicite tanto `openid email` como los alcances de operación que necesita su cliente. Llame al `userinfo_endpoint` detectado (`GET /v1/oauth/userinfo`) con el token de acceso en el encabezado Bearer. Una respuesta exitosa contiene:

```json
{
  "sub": "123",
  "email": "person@example.com",
  "email_verified": true,
  "name": "Example User",
  "org_id": 456
}
```

`sub` es el identificador estable de la persona usuaria; `org_id` es la organización seleccionada durante el consentimiento. El endpoint requiere ambos alcances de identidad y devuelve `403` si falta alguno. Devuelve `403` con `error=access_denied` si la cuenta no tiene un perfil de correo electrónico verificado, en lugar de afirmar que un correo electrónico sin verificar es confiable. Los tokens no válidos, vencidos, revocados o con audiencia incorrecta devuelven `401`. Los tokens de sesión humana y las claves de API de organización no pueden llamar a userinfo. No se emite ningún token de ID.

## Permisos disponibles

| Familia | Scopes |
| --- | --- |
| Agentes e importaciones de agentes | `agents:read`, `agents:write` |
| Llamadas | `calls:read`, `calls:write` |
| Números de teléfono, quienes llaman bloqueados y VoIP | `numbers:read`, `numbers:write` |
| Conocimiento | `knowledge:read`, `knowledge:write` |
| Campañas | `campaigns:read`, `campaigns:write` |
| Integraciones, endpoints de webhook, servidores MCP | `integrations:read`, `integrations:write` |
| Voces | `voices:read` |
| Escenarios de prueba, ejecuciones de prueba, validación | `testing:read`, `testing:write` |
| Facturación | `billing:read` |
| Identidad de la cuenta y correo electrónico verificado | `openid`, `email` (ambos obligatorios para userinfo) |
| Conexión persistente | `offline_access` (siempre incluido) |

GET, HEAD y OPTIONS usan permisos de lectura; los demás métodos usan permisos de escritura. Las modificaciones de voces y facturación no están disponibles mediante OAuth; `POST /v1/voices/preview` usa `voices:read` porque previsualiza una voz sin cambiar su configuración. Las herramientas MCP aplican el permiso de su operación REST subyacente. Las transferencias entre organizaciones se rechazan incluso cuando el usuario que autoriza pertenece a ambas organizaciones. Otras familias de API, incluida la administración de claves de API y la configuración de cuentas humanas, no están disponibles mediante OAuth. La ausencia de un permiso en una operación REST devuelve `403` con `WWW-Authenticate: Bearer error="insufficient_scope", scope="..."`. Los tokens de acceso no válidos o vencidos devuelven `401`.


### Señales de autenticación de herramientas MCP

Cada herramienta en `tools/list` incluye `securitySchemes: [{"type": "oauth2", "scopes": ["agents:read"]}]`, con el permiso de la operación REST de esa herramienta. Las herramientas de documentación pública usan una lista de permisos vacía y aun así requieren una conexión autenticada.

Un token válido que no tenga el permiso de una herramienta recibe HTTP `200` con un `result` de JSON-RPC que contiene `isError: true`, texto explicativo en `content` y `_meta["mcp/www_authenticate"]`. Este último es un arreglo que contiene un desafío Bearer con `resource_metadata`, `error="insufficient_scope"`, `error_description` y el `scope` requerido. La herramienta no se ejecuta. Usa este desafío para solicitar consentimiento ampliado. La autenticación faltante o no válida sigue devolviendo HTTP `401` con `WWW-Authenticate`; los errores de permisos REST siguen devolviendo HTTP `403`.

## Retención de credenciales

La API ejecuta `python manage.py oauth_cleanup` cada hora en staging y producción. Elimina solicitudes de autorización y códigos de dispositivo vencidos. Los tokens de acceso vencidos, los códigos de autorización y los hashes de tokens de actualización se depuran solo después de que se revoque su concesión o toda la familia deje de ser válida. Los hashes usados se conservan mientras la familia tenga un token de actualización, código de autorización, código de dispositivo aprobado o token de acceso utilizable, para que la limpieza no pueda deshabilitar la detección de repetición.
