Tu primer token en cinco minutos
Registra un cliente, genera PKCE, autoriza y canjea el código: de cero a un access token de UTILIA OS con curl, JavaScript o Python.
Actualizado el . 4 min de lectura
Esta guía te lleva de cero a un access token funcional sin salir de la página. Solo necesitas una cuenta de UTILIA OS con la que autorizar y curl o cualquier cliente HTTP. Al final comprobarás el token pidiendo los datos de la persona a GET /api/oauth/userinfo. Antes de empezar, retén estos tres plazos: marcan cuánto tiempo tienes en cada paso.
Tres plazos que vas a usar
- Código de autorización
- 60segundos
- Sirve una sola vez: canjéalo nada más recibirlo.
- Access token
- 1hora
- Después, renuévalo con el refresh token.
- Refresh token
- 90días
- Desde la autorización. Cambia en cada renovación.
El orden completo de la conversación entre tu aplicación, el navegador y UTILIA OS está dibujado en Flujo de autorización.
Registra tu aplicación
Envía una petición al endpoint de registro dinámico. Es público y no necesita autenticación.
POST/api/oauth/registerRegistro dinámico de clientes OAuth (público)
curl -X POST https://os.utilia.ai/api/oauth/register \ -H "Content-Type: application/json" \ -d '{ "client_name": "Agenda Nubeta (pruebas)", "redirect_uris": ["http://localhost:3000/callback"] }'Respuesta:
JSON{ "client_id": "mcp_3f9a1c2b7d4e5f60718293a4b5c6d7e8", "client_id_issued_at": 1743897600, "redirect_uris": ["http://localhost:3000/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none", "client_name": "Agenda Nubeta (pruebas)" }Con
token_endpoint_auth_method: "none"el cliente es público y no tiene secreto: PKCE lo protege. Las direcciones de vuelta deben usarhttps, salvolocalhost,127.0.0.1y[::1], que admitenhttp. Si prefieres crear la aplicación desde la interfaz, con clave secreta y enlaces legales, sigue Activar OAuth en tu aplicación.Tres cosas del registro dinámico que conviene saber antes de seguir:
- Es público y tiene límite. No pide cuenta y admite 30 registros por hora desde una misma dirección IP.
- Pon el nombre de tu aplicación. Un cliente público con el mismo nombre y las mismas direcciones de vuelta que otro ya registrado devuelve ese mismo
client_id: si copias el ejemplo tal cual, compartirías cliente con quien haya hecho lo mismo. - Cualquier persona puede autorizarlo. El cliente no pertenece a ninguna organización: lo autoriza cualquiera con cuenta en UTILIA OS, sobre los datos de su propia organización. Si tu aplicación es solo para tu equipo, lee Quién puede autorizar tu aplicación.
Genera el par PKCE
Crea un
code_verifieraleatorio y deriva de él elcode_challengecon SHA-256 en Base64URL sin relleno.CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=' | tr '/+' '_-') CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr -d '=' | tr '/+' '_-') echo "code_verifier: $CODE_VERIFIER" echo "code_challenge: $CODE_CHALLENGE"Guarda el
code_verifier: lo necesitarás en el paso 5. Nunca viaja en la URL de autorización.Abre la URL de autorización
Monta la URL con estos parámetros y ábrela en el navegador. Los espacios de
scopevan codificados como%20.https://os.utilia.ai/api/oauth/authorize?client_id=CLIENT_ID&redirect_uri=http://localhost:3000/callback&response_type=code&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&scope=openid%20profile%20email&state=VALOR_ALEATORIO- client_idstringobligatorio
- El identificador del paso 1.
- redirect_uristringobligatorio
- Una de las direcciones registradas, exactamente igual.
- response_typestringobligatorio
- Siempre code.
- code_challengestringobligatorio
- El challenge del paso 2.
- code_challenge_methodstringobligatorio
- Siempre S256. No se admite plain.
- scopestring
- Scopes separados por espacios. Si lo omites, se piden solo openid, profile y email.
- statestring
- Valor aleatorio contra la falsificación de peticiones. Vuelve tal cual en la redirección.
UTILIA OS pide a la persona que inicie sesión, si no lo ha hecho, y le muestra la pantalla de consentimiento.
Recoge el código
Cuando la persona autoriza, UTILIA OS la devuelve a tu
redirect_uricon el código:http://localhost:3000/callback?code=abc123def456&state=VALOR_ALEATORIOComprueba que
statecoincide con el que enviaste y quédate concode. Tienes 60 segundos para canjearlo.Canjea el código por tokens
POST/api/oauth/tokenCanje del código por tokens
El endpoint admite
application/x-www-form-urlencoded(lo habitual en OAuth) y JSON.curl -X POST https://os.utilia.ai/api/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d 'grant_type=authorization_code' \ -d 'code=AUTH_CODE' \ -d 'redirect_uri=http://localhost:3000/callback' \ -d 'code_verifier=CODE_VERIFIER' \ -d 'client_id=CLIENT_ID'Respuesta:
JSON{ "access_token": "TU_ACCESS_TOKEN", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "TU_REFRESH_TOKEN", "scope": "openid profile email", "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im9pZGMtcHJvZC0xIn0..." }Cada vez que renuevas, recibes un refresh token nuevo y el anterior deja de valer: guarda siempre el último. Lo explica Rotación del refresh token.
Usa el token
Pide los datos de la persona:
GET/api/oauth/userinfoDatos de la persona autenticada (access token con openid)
curl -H "Authorization: Bearer ACCESS_TOKEN" \ https://os.utilia.ai/api/oauth/userinfoRespuesta:
JSON{ "sub": "3b1f6c2e-8a4d-4f0b-9c7e-2d5a1e6f8b90", "name": "María García", "given_name": "María", "family_name": "García", "email": "maria@ejemplo.example", "email_verified": true }Si la persona tiene foto de perfil, también llega
picture. Para trabajar con sus datos, pide en el paso 3 los scopes de un servidor MCP junto con suresourcey llama a ese servidor con el token. Lo tienes en Scopes y recursos.
Si algo falla
invalid_grant: el código ha caducado, ya se usó o elcode_verifierno corresponde alcode_challenge. Genera un par PKCE nuevo y vuelve al paso 3.invalid_grantconredirect_uri mismatch: la dirección del canje no es idéntica a la de la autorización.http://localhost:3000/callbackyhttp://localhost:3000/callback/son distintas.invalid_requestconcode_verifier is required for PKCE: falta elcode_verifieren el canje.
El resto de casos está en Problemas frecuentes con OAuth.