Autenticación
Todas las APIs de IDCloud (contratos Web & SDK y API) usan OAuth2 con JWT Bearer Grant Type (RFC 7523). Usted genera una aserción JWT de corta duración en su back-end, la intercambia por un token Bearer y usa ese token en cada llamada posterior.
La aserción JWT debe generarse únicamente en su back-end. Nunca exponga su clave privada en código front-end, aplicaciones móviles, repositorios ni logs.
Obtención de credenciales
Antes de poder generar tokens, necesita una cuenta de servicio aprovisionada por Unico. Contacte al soporte de Unico y proporcione:
- Nombre de la cuenta de servicio (máximo 12 caracteres)
- Nombre, correo electrónico y teléfono del responsable (solo números de Brasil, EE. UU. o México)
Recibirá:
- Nombre único de cuenta
- Tenant ID
- Payload JWT base
- Archivo de clave privada (formato
.pem)
Mantenga cuentas de servicio separadas para UAT y Producción.
Construcción de la aserción JWT
La aserción es un JWT en formato JWS compacto: {Base64url(Header)}.{Base64url(Payload)}.{Base64url(Signature)}.
{
"alg": "RS256",
"typ": "JWT"
}
| Claim | Valor | Notas |
|---|---|---|
iss | <account_name>@<tenant_id>.iam.acesso.io | Proporcionado con sus credenciales |
aud | https://identityhomolog.acesso.io (UAT) o https://identity.acesso.io (Producción) | Debe coincidir con el host del endpoint de token |
scope | * | Otorga todos los permisos |
iat | Marca de tiempo Unix (segundos) | Hora en que se emitió el JWT |
exp | iat + máximo 3600 | No puede superar 1 hora desde iat |
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": 1738086000,
"exp": 1738089600
}
Firme el header + payload usando RS256 (RSA + SHA-256) con la clave privada .pem proporcionada por Unico.
Cualquier campo no listado anteriormente (p. ej. sub, jti, nbf) causará un error 1.2.22. Use solo los claims mostrados.
Solicitud del token
El endpoint de token es el mismo para ambos contratos:
| Entorno | Endpoint |
|---|---|
| Producción | POST https://identity.acesso.io/oauth2/token |
| UAT | POST https://identityhomolog.acesso.io/oauth2/token |
| Parámetro | Valor |
|---|---|
Content-Type | application/x-www-form-urlencoded |
grant_type | urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion | Su JWT firmado |
- cURL
- Node.js
- Python
curl -X POST https://identity.acesso.io/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
-d "assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
import jwt from 'jsonwebtoken';
import fs from 'fs';
import qs from 'querystring';
const privateKey = fs.readFileSync('./private-key.pem');
const now = Math.floor(Date.now() / 1000);
const assertion = jwt.sign(
{
aud: 'https://identity.acesso.io',
scope: '*',
iat: now,
exp: now + 3600,
},
privateKey,
{ algorithm: 'RS256' }
);
const res = await fetch('https://identity.acesso.io/oauth2/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: qs.stringify({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion,
}),
});
const { access_token, expires_in } = await res.json();
import time
import jwt # PyJWT
import requests
with open("private-key.pem", "rb") as f:
private_key = f.read()
now = int(time.time())
assertion = jwt.encode(
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": now,
"exp": now + 3600,
},
private_key,
algorithm="RS256",
)
response = requests.post(
"https://identity.acesso.io/oauth2/token",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion,
},
)
token_data = response.json()
access_token = token_data["access_token"]
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
| Campo | Tipo | Descripción |
|---|---|---|
access_token | string | Token de acceso JWT. Úselo en Authorization: Bearer <token> en todas las llamadas a la API. |
expires_in | integer | Tiempo de expiración en segundos. Ejemplo: 3600. |
token_type | string | Siempre Bearer. |
Uso del token
Agregue el token al encabezado Authorization de cada solicitud a la API. El encabezado es idéntico para ambos contratos — lo que difiere es el host y el path de la API que está llamando:
| Contrato | Host de producción | Host de UAT |
|---|---|---|
| Web & SDK | https://api.idcloud.unico.app | https://api.idcloud.uat.unico.app |
| API | https://api.id.unico.app | https://api.id.uat.unico.app |
Web & SDK — Authorization es el único encabezado de autenticación requerido:
curl -X POST https://api.idcloud.unico.app/client/v1/process \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'
API — Authorization se usa junto con el encabezado APIKEY:
curl -X POST https://api.id.unico.app/processes/v1 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "APIKEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'
Renovación del token
Los tokens expiran después de 3600 segundos. Implemente la renovación proactiva en su back-end:
- Registre
expires_inde la respuesta del token y almacene la marca de tiempo de expiración. - Solicite un nuevo token cuando queden 10 minutos o menos antes de la expiración.
- Nunca espere un
401en producción para activar la renovación.
Referencia de API
La especificación OpenAPI completa para el endpoint de token está disponible en authentication.yaml.
| Método | Path | Descripción |
|---|---|---|
POST | /oauth2/token | Intercambia una aserción JWT firmada por un token de acceso Bearer |
Códigos de error
| Código | Descripción | Acción |
|---|---|---|
1.0.1 | El ID proporcionado en la formación de iss es incorrecto | Verifique que el campo iss coincida con el tenant ID proporcionado al generar la clave privada |
1.0.14 | La aplicación no está activa | Consulte con el gestor del proyecto si la aplicación utilizada está activa |
1.1.1 | El parámetro scope no fue proporcionado | Agregue "scope": "*" a su payload JWT |
1.2.4 | Aserción JWT inválida | La aserción JWT ya no es válida. Dos causas: (a) el tiempo actual supera exp (JWT verdaderamente expirado — genere una nueva aserción para cada solicitud de token); o (b) exp supera iat + 3600 (vida útil demasiado larga — limite exp a iat + 3600). |
1.2.5 | La validación del JWT falló | El JWT no puede ser validado. Verifique los parámetros y asegúrese de que fue firmado con RS256 y la clave privada correcta |
1.2.6 | La clave privada ya no es válida | La clave privada usada para firmar el JWT ya no es aceptable. Solicite nuevas credenciales para la cuenta |
1.2.7 | El JWT ya fue utilizado | El JWT ya no es aceptable porque ya fue utilizado. Genere una nueva aserción para cada solicitud de token |
1.2.11 | La cuenta no está activa | La cuenta utilizada no está activa |
1.2.14 | La cuenta carece de los permisos necesarios | La cuenta utilizada no tiene los permisos necesarios |
1.2.18 | Cuenta temporalmente bloqueada | La cuenta ha sido temporalmente bloqueada por exceder el número de intentos de autenticación inválidos |
1.2.19 | Suplantación de usuario no autorizada | El JWT contiene un claim sub que apunta a una cuenta no autorizada para suplantación. Elimine el claim sub del payload. |
1.2.20 | Error al decodificar el JWT | No se pudo decodificar el JWT. Verifique el formato del token y que haya sido firmado con RS256. |
1.2.21 | Clave privada incorrecta / Autenticación fallida | La firma del JWT no pudo verificarse con ninguna clave conocida para esta cuenta. Compruebe que está usando la clave privada .pem correcta para esta cuenta de servicio y entorno. |
1.2.22 | Campos no permitidos en el payload | El JWT contiene campos de payload adicionales que no están permitidos. Elimine cualquier claim no listado en esta guía (p. ej. sub, jti, nbf). Nota: si incluyó un claim sub y recibió 1.2.19, ese error tiene precedencia. |
1.3.1 | Restricción de acceso por IP | Su IP no está en la lista de permitidos para esta cuenta |
1.3.2 | Restricción de acceso por horario | La solicitud está fuera de la ventana de tiempo permitida para esta cuenta |
Próximos pasos
- Entornos — hosts de sandbox vs producción
- Web & SDK — Crear proceso — primera llamada tras la autenticación
- API — Crear proceso — primera llamada tras la autenticación