OAuth: visión general
Qué te permite hacer el servidor OAuth 2.1 y OpenID Connect de UTILIA OS, qué endpoints expone y cuánto duran sus tokens.
Actualizado el . 7 min de lectura
UTILIA OS incluye un servidor de autorización OAuth 2.1 con OpenID Connect. Sirve para dos cosas: que las personas entren en tu aplicación con su cuenta de UTILIA OS (el botón «Iniciar sesión con UTILIA») y que un cliente, como un asistente de IA, trabaje con sus datos a través de los servidores MCP de UTILIA OS, siempre con su consentimiento y nunca más allá de sus permisos ni del plan de su organización.
Qué puedes hacer con un token
El access token que obtienes al final del flujo actúa en nombre de una persona y no sirve para todo. No lo confundas con la clave de API de tu aplicación:
Token OAuth o clave de API
En nombre de una persona
Access token OAuth
En nombre de tu aplicación
Clave de API
Las direcciones de los servidores MCP están en Copiloto y MCP, y la clave de API, en Autenticación con clave de acceso.
Cómo funciona el flujo
Ciclo de una integración OAuth
Panel o /api/oauth/register
Obtienes el client_id y, con servidor propio, la clave secreta.userinfo o servidor MCP
Usar el token
Durante 1 hora, en la cabecera Authorization: Bearer./api/oauth/revoke
Revocar
Al cerrar sesión, para que los tokens dejen de valer.
Los clientes MCP descubren antes las direcciones del servidor en /.well-known/.... Solo se admite el flujo de código de autorización (response_type=code) con PKCE obligatorio y método S256. No hay flujo implícito, ni híbrido, ni client_credentials, ni device_code.
Dos endpoints se retiran el 16 de octubre de 2026
GET /api/oauth/user-scopes y POST /api/oauth/apps/revoke siguen respondiendo, pero llevan las cabeceras Deprecation: true y Sunset: Thu, 16 Oct 2026 00:00:00 GMT. Cámbialos por GET /api/oauth/user/scopes y POST /api/oauth/apps/:clientId/revoke antes de esa fecha. Detalle en Cambios de OAuth.
Estándares implementados
- RFC 6749/api/oauth/authorize, /api/oauth/token
- Marco OAuth 2.0: autorización y emisión de tokens.
- RFC 7636code_challenge
- PKCE, obligatorio en todos los flujos y solo con S256.
- RFC 7591/api/oauth/register
- Registro dinámico de clientes, sin intervención manual.
- RFC 7009/api/oauth/revoke
- Revocación de access tokens y refresh tokens.
- RFC 7662/api/oauth/introspect
- Introspección: estado y metadatos de un access token.
- RFC 8414/.well-known/oauth-authorization-server
- Metadatos del servidor de autorización.
- RFC 8707resource
- Indicadores de recurso: el token queda atado a un servidor MCP concreto.
- RFC 9728/.well-known/oauth-protected-resource
- Metadatos de cada recurso protegido y de sus scopes.
- OpenID Connect Core 1.0/api/oauth/userinfo, /api/oauth/jwks
- id_token firmado con RS256 y datos de la persona.
Endpoints
Descubrimiento (públicos)
No necesitan ninguna credencial. Viven en la raíz del dominio, fuera de /api. El detalle de cada uno está en Descubrimiento del servidor.
GET /.well-known/oauth-authorization-server: metadatos del servidor de autorización.GET /.well-known/openid-configuration: los mismos, ampliados con los campos de OpenID Connect.GET /.well-known/oauth-protected-resource: metadatos de un recurso; con?resource=devuelve los del servidor MCP indicado.GET /.well-known/mcp-crm.json,mcp-work.json(y su aliasmcp-dev.json),mcp-finance.json,mcp-marketing.json,mcp-chat.jsonymcp-rrhh.json: atajos con los metadatos de cada servidor MCP.GET /.well-known/jwks.json: claves públicas para verificar elid_token.GET /.well-known/resource-server.json: variante antigua deoauth-protected-resource, solo por compatibilidad.
Flujo de autorización
GET /api/oauth/authorize: inicia la solicitud y lleva a la persona a la pantalla de consentimiento.POST /api/oauth/authorize: registra la decisión de la persona. Solo lo llama la propia pantalla de consentimiento.POST /api/oauth/token: canjea el código por tokens o renueva con el refresh token.POST /api/oauth/register: registro dinámico de clientes.
Ciclo de vida de los tokens
POST /api/oauth/revoke: revoca un token. Responde siempre200.POST /api/oauth/introspect: devuelve el estado de un access token emitido a tu cliente o{ "active": false }. Solo para clientes confidenciales autenticados con su secreto; un cliente público no puede usarlo.
OpenID Connect
GETyPOST /api/oauth/userinfo: datos de la persona. Exige un access token con el scopeopenid.GET /api/oauth/jwks: claves públicas (las mismas que/.well-known/jwks.json).GETyPOST /api/oauth/logout: cierre de sesión iniciado por tu aplicación. Detalle en Cierre de sesión desde tu aplicación.
Consulta pública
GET /api/oauth/clients/:clientId: dice si un cliente existe y si es una aplicación propia de UTILIA OS. Si no existe responde{ "known": false }con200, para que nadie pueda enumerar clientes.GET /api/oauth/scopes?scopes=...: descripción en castellano de los scopes que indiques.
Aplicaciones de la propia persona (sesión de UTILIA OS)
Estos endpoints los usa la interfaz de UTILIA OS con la sesión de la persona; son los que hay detrás de Perfil › Aplicaciones.
GET /api/oauth/apps: aplicaciones que la persona ha autorizado, con los permisos que cada una puede ejercer de verdad.POST /api/oauth/apps/:clientId/revoke: retira el acceso de una aplicación. No lleva cuerpo.GET /api/oauth/user/scopes: scopes que la persona puede conceder, recortados por sus permisos, por el plan de su organización y, si lo indicas, porresource. Conclient_idañade la información pública del cliente.
Respuesta de GET /api/oauth/apps
Devuelve una lista. Cada elemento tiene esta forma:
- clientIdstringobligatorio
- Identificador público del cliente OAuth.
- clientNamestringobligatorio
- Nombre de la aplicación.
- clientUristring | null
- Web que declaró la aplicación al registrarse.
- logoUristring | null
- Logotipo que declaró la aplicación al registrarse.
- scopestringobligatorio
- Obsoleto, se retira el 1 de febrero de 2027. Los mismos scopes que permissions, separados por espacios. Usa permissions.
- permissionsarrayobligatorio
- Permisos que la aplicación puede ejercer con el plan actual. Cada elemento: scope, description (en castellano) e impact (destructive, write, read o identity). Primero los irreversibles.
- permissionCountnumberobligatorio
- Número de permisos ejercibles. Siempre igual a la longitud de permissions.
- unavailablePermissionCountnumberobligatorio
- Permisos concedidos que el plan actual no deja ejercer.
- unavailableModulesarrayobligatorio
- Aplicativos no contratados de los que vienen esos permisos. Cada elemento: key y label.
- authorizedAtstring (ISO 8601)obligatorio
- Fecha de la autorización vigente más antigua de esta aplicación.
- lastUsedAtstring (ISO 8601) | null
- Último uso registrado entre las autorizaciones vigentes. Nulo quiere decir que no consta ninguno.
[
{
"clientId": "claude-desktop",
"clientName": "Claude Desktop",
"clientUri": "https://claude.ai",
"logoUri": null,
"scope": "crm:clients:view email openid profile",
"permissions": [
{ "scope": "crm:clients:view", "description": "Ver clientes del CRM", "impact": "read" },
{ "scope": "email", "description": "Acceso a tu dirección de correo electrónico", "impact": "identity" },
{ "scope": "openid", "description": "Autenticación OpenID Connect", "impact": "identity" },
{ "scope": "profile", "description": "Acceso a tu nombre y foto de perfil", "impact": "identity" }
],
"permissionCount": 4,
"unavailablePermissionCount": 12,
"unavailableModules": [{ "key": "marketing", "label": "Marketing" }],
"authorizedAt": "2026-06-10T10:00:00.000Z",
"lastUsedAt": "2026-07-27T09:12:44.000Z"
}
]Desde el 28 de julio de 2026, scope ya no lista todo lo que hay en el token, sino solo lo que el plan de la organización deja ejercer, con sus dos puertas: el aplicativo contratado y la capacidad activa dentro de él. Lo demás no se ha revocado: sigue concedido y se cuenta en unavailablePermissionCount. La fuente de verdad de lo que se puede ejecutar es siempre el servidor MCP.
Tiempos y límites
- Access token3.600 s (1 hora)
- Renuévalo con el refresh token.
- Refresh token90 días
- Contados desde la autorización. Rotar no alarga ese plazo.
- Rotación del refresh tokenSiempre
- Cada renovación entrega un refresh token nuevo y anula el anterior. Reutilizar uno ya rotado revoca toda la cadena de esa autorización.
- Código de autorización60 s
- De un solo uso. Si se reutiliza, se revocan los tokens emitidos con él.
- id_token3.600 s (1 hora)
- JWT firmado con RS256. Solo se emite si se concede el scope openid y solo en el canje del código, no en las renovaciones.
- Solicitud pendiente de consentimiento10 minutos
- Si la persona tarda más en decidir, tiene que empezar de nuevo desde tu aplicación.
- PKCES256obligatorio
- code_verifier de 43 a 128 caracteres del conjunto [A-Za-z0-9-._~]; code_challenge en Base64URL sin relleno.
- Autenticación del clientenone, client_secret_basic, client_secret_post
- Los clientes del registro dinámico usan none por defecto.
Los tokens son cadenas opacas, sin prefijo ni estructura: no intentes leerlos. Para saber si un access token sigue vivo, usa la introspección. El detalle está en Canje, revocación e introspección de tokens.
Por dónde seguir
- Tu primer tokenDe cero a un token funcional, paso a paso.
- Activar OAuth en tu aplicaciónCredenciales, direcciones de vuelta y tipo de aplicación en el panel.
- Flujo de autorizaciónParámetros, respuestas y errores de /api/oauth/authorize.
- Scopes y recursosCatálogo de scopes, conjuntos y qué viaja con cada servidor.
- Iniciar sesión con UTILIA en Next.jsEl botón completo con Auth.js.
- Problemas frecuentesErrores habituales y cómo resolverlos.