Skip to content

Metadata

Owner: sso-team · Lifecycle: active · Last Reviewed: 2026-02-13 · Support: #sso-core

SSO Core — Integración

APIs Expuestas

Todos los endpoints usan el prefijo /api/v1. Los endpoints protegidos requieren una cookie sso_session válida o un header Authorization: Bearer <token>.

Autenticación (/auth)

MétodoEndpointDescripciónAutenticación
POST/auth/signupRegistrar usuarioPúblico (rate limit: 5/h)
POST/auth/signinIniciar sesión (establece cookie)Público (rate limit: 10/15min)
POST/auth/signoutCerrar sesión (refresh token legacy)Bearer token
POST/auth/logoutCerrar sesión SSO (cookie)Cookie sso_session
POST/auth/refreshRenovar tokensPúblico (rate limit: 30/min)
POST/auth/authorizeGenerar authorization codeCookie sso_session
POST/auth/validate-codeValidar code y obtener contextoPúblico (backend-to-backend)
POST/auth/tokenIntercambiar code por session tokenPúblico (backend-to-backend)
POST/auth/verify-sessionVerificar session token de appPúblico (backend-to-backend)

Usuarios (/user)

MétodoEndpointDescripciónAutenticación
GET/user/profileObtener perfil del usuario autenticadoCookie sso_session
PUT/user/profileActualizar perfil (datos + direcciones)Cookie sso_session
GET/user/tenantsTenants del usuario con apps habilitadasCookie sso_session
GET/PUT/DELETE/user/:userIdCRUD por IDBearer token

Tenants (/tenant)

MétodoEndpointDescripciónAutenticación
POST/tenantCrear tenantCookie + System Admin
GET/tenantListar tenantsCookie sso_session
POST/tenant/:id/membersInvitar miembroCookie + Tenant Admin
GET/tenant/:id/membersListar miembrosCookie + Tenant Member
PUT/tenant/:id/members/:mIdCambiar rolCookie + Tenant Admin
DELETE/tenant/:id/members/:mIdEliminar miembroCookie + Tenant Admin
GET/tenant/:id/appsApps del tenantCookie + Tenant Member

Roles (/role)

MétodoEndpointDescripciónAutenticación
POST/roleCrear rol personalizadoCookie sso_session
GET/role/tenant/:tenantIdListar roles del tenantCookie + Tenant Member
GET/PUT/DELETE/role/:roleIdCRUD de rolCookie sso_session
POST/role/:roleId/permissionAgregar permisoCookie sso_session
GET/role/:roleId/permissionListar permisosCookie sso_session
DELETE/role/:roleId/permission/:pIdEliminar permisoCookie sso_session

Aplicaciones (/applications)

MétodoEndpointDescripciónAutenticación
POST/applicationsCrear aplicaciónCookie + System Admin
GET/applicationsListar todas (?active=true)Cookie + System Admin
POST/applications/tenant/:tId/enableHabilitar app para tenantCookie + System Admin
POST/applications/tenant/:tId/:appId/grantDar acceso a usuarioCookie + Tenant Admin
POST/applications/tenant/:tId/:appId/grant-bulkAcceso masivoCookie + Tenant Admin
GET/applications/user/:tenantIdApps del usuario autenticadoCookie sso_session

App Resources (/app-resources)

MétodoEndpointDescripciónAutenticación
POST/app-resourcesRegistrar recursos de appCookie sso_session
GET/app-resources/:appIdObtener recursos de appCookie sso_session
GET/app-resources/tenant/:tId/availableRecursos disponibles en tenantCookie sso_session

OTP — 2FA (/otp)

MétodoEndpointDescripción
POST/otp/generateGenerar secreto y QR code
POST/otp/verifyVerificar token y activar 2FA
POST/otp/validateValidar OTP durante login (con tempToken)
POST/otp/backup-codeUsar código de respaldo
POST/otp/disableDesactivar 2FA
GET/otp/status/:userIdVerificar si 2FA está activo

Ejemplos de Consumo

Flujo Completo SSO (Authorization Code)

Paso a Paso con cURL

1. Login en SSO:

bash
curl -X POST http://localhost:3000/api/v1/auth/signin \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"nuid":"admin@example.com","password":"admin123"}'

2. Generar authorization code:

bash
curl -X POST http://localhost:3000/api/v1/auth/authorize \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "tenantId": "uuid-tenant",
    "appId": "crm",
    "redirectUri": "http://localhost:4200/callback"
  }'

3. Intercambiar code por session:

bash
curl -X POST http://localhost:3000/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{"authCode":"abc123","appId":"crm"}'

4. Verificar sesión:

bash
curl -X POST http://localhost:3000/api/v1/auth/verify-session \
  -H "Content-Type: application/json" \
  -d '{"sessionToken":"jwt-from-step-3","appId":"crm"}'

Contratos

Registro de Usuario

Request:

json
{
  "email": "user@example.com",
  "password": "SecurePass123!",
  "firstName": "Juan",
  "lastName": "Pérez"
}

Response (201):

json
{
  "success": true,
  "message": "User created successfully",
  "user": {
    "userId": "uuid",
    "email": "user@example.com"
  }
}

Authorization Code

Request (/auth/authorize):

json
{
  "tenantId": "uuid-del-tenant",
  "appId": "crm",
  "redirectUri": "https://crm.empire.com/callback"
}

Response:

json
{
  "success": true,
  "authCode": "code-one-time-use",
  "redirectUri": "https://crm.empire.com/callback?code=code-one-time-use"
}

Token Exchange

Request (/auth/token):

json
{
  "authCode": "code-from-authorize",
  "appId": "crm"
}

Response:

json
{
  "success": true,
  "sessionToken": "jwt-session-token",
  "expiresAt": "2026-02-13T19:00:00.000Z",
  "user": {
    "userId": "uuid",
    "email": "user@example.com",
    "firstName": "Juan",
    "lastName": "Pérez"
  },
  "tenant": {
    "tenantId": "uuid",
    "name": "Mi Empresa",
    "slug": "mi-empresa",
    "role": "admin"
  }
}

Formato de Errores

json
{
  "error": "ERROR_CODE",
  "message": "Descripción legible del error",
  "details": [],
  "timestamp": "2026-02-12T19:00:00.000Z"
}
Código HTTPError CodeDescripción
400VALIDATION_ERRORDatos de entrada inválidos
401UNAUTHORIZEDNo autenticado
403FORBIDDENSin permisos suficientes
403TENANT_ACCESS_DENIEDSin acceso al tenant
403APP_ACCESS_DENIEDSin acceso a la aplicación
404NOT_FOUNDRecurso no encontrado
409APP_ID_EXISTSID de app ya existe
429Rate limit excedido

Autenticación

La autenticación principal usa cookies HttpOnly:

typescript
{
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'lax',
  maxAge: 24 * 60 * 60 * 1000,
  domain: process.env.COOKIE_DOMAIN  // solo en producción
}

JWKS Endpoint

La clave pública se distribuye vía:

GET /.well-known/jwks.json

Las aplicaciones pueden verificar tokens sin conexión directa al SSO Core.


Casos de Uso: Integrar una Aplicación

1. Registrar la aplicación

bash
curl -X POST http://localhost:3000/api/v1/applications \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "appId": "crm",
    "name": "CRM System",
    "url": "https://crm.empire.com",
    "description": "Sistema de gestión de clientes"
  }'

2. Habilitar para tenant

bash
curl -X POST http://localhost:3000/api/v1/applications/tenant/{tenantId}/enable \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"applicationId": "uuid-de-la-aplicacion"}'

3. Otorgar acceso a usuarios

bash
curl -X POST http://localhost:3000/api/v1/applications/tenant/{tenantId}/{appId}/grant \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"userId": "uuid-del-usuario"}'

4. Implementar callback en tu backend

typescript
// routes/auth.ts (en tu aplicación)
router.post('/callback', async (req, res) => {
  const { code } = req.body;

  const response = await axios.post(`${SSO_URL}/api/v1/auth/token`, {
    authCode: code,
    appId: 'crm'
  });

  const { sessionToken, expiresAt, user, tenant } = response.data;

  res.cookie('app_session', sessionToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 24 * 60 * 60 * 1000
  });

  res.json({ success: true, user, tenant });
});

5. Middleware de verificación de sesión

typescript
// middleware/ssoAuth.ts (en tu aplicación)
export async function ssoAuthMiddleware(req, res, next) {
  const sessionToken = req.cookies['app_session'];

  if (!sessionToken) {
    return res.status(401).json({ error: 'No session' });
  }

  const response = await axios.post(`${SSO_URL}/api/v1/auth/verify-session`, {
    sessionToken,
    appId: 'crm'
  });

  if (!response.data.valid) {
    return res.status(401).json({ error: 'Invalid session' });
  }

  req.ssoUser = response.data.user;
  req.ssoTenant = response.data.tenant;
  next();
}

Tip: Para mejorar el rendimiento, cachea el resultado de /verify-session localmente (ej. Redis con TTL de 60s).

6. Registrar recursos para RBAC

bash
curl -X POST http://localhost:3000/api/v1/app-resources \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "appId": "crm",
    "resources": [
      { "resource": "contacts", "action": "create", "category": "sales" },
      { "resource": "contacts", "action": "read", "category": "sales" },
      { "resource": "invoices", "action": "create", "category": "billing" },
      { "resource": "reports", "action": "read", "category": "analytics" }
    ]
  }'

Troubleshooting

ErrorCausaSolución
APP_ACCESS_DENIEDUsuario sin acceso a la app en el tenantVerificar TenantApp y UserAppAccess
APP_NOT_ENABLED_FOR_TENANTApp no habilitada para el tenantUsar /applications/tenant/:id/enable
INVALID_AUTH_CODECode ya usado o expiradoGenerar nuevo code (un solo uso, 5 min TTL)