Guía de Integración SSO JWT
Integración por SSO: la empresa firma un JWT con el secreto compartido, redirige al usuario al endpoint de Nume, y Nume crea o reactiva la cuenta, inicia sesión en Nume.
Flujo
Empresa
1. Portal
Usuario autenticado
Empresa
2. Firma JWT
Con el secreto compartido
Empresa
3. Redirect
/integrations/sso/…?token=…
Nume
4. Login en Nume
Valida, crea o reactiva e inicia sesión
- El usuario está autenticado en el portal de la empresa.
- La empresa firma un JWT con los datos del usuario y el secreto compartido.
- Redirige el browser a Nume con ese JWT en la query.
- Nume valida el JWT, crea el usuario si no existe (o lo reactiva si estaba desactivado), inicia sesión y redirige a la app.
Requisitos previos
Antes de usar este flujo, Nume les entrega:
- API host — base URL de la API de Nume (prod o testing)
- Integration UUID — identifica la integración en la URL
- JWT secret — clave compartida para firmar el JWT (algoritmo HS256)
Endpoint
Método GET. La empresa debe redirigir el browser del usuario a esta URL (no es una llamada server-to-server).
URL:
GET /integrations/sso/{integrationUuid}?token={jwt}Claims del JWT
Algoritmo HS256. El secret es el valor entregado por Nume.
Campos requeridos
| Campo | Tipo | Descripción |
|---|---|---|
email o external_id | string | Exactamente uno de los dos. No enviar email y external_id juntos. |
iat | number | Unix timestamp (segundos) de emisión. El token se rechaza si tiene más de 5 minutos de antigüedad. |
Campos opcionales
| Campo | Tipo | Descripción |
|---|---|---|
full_name | string | Nombre completo del usuario |
data.first_name | string | Nombre |
data.last_name | string | Apellido |
data.dni | string | Documento |
data.date_of_birth | string | Fecha ISO 8601 UTC, ej. "1995-07-21T00:00:00.000Z" |
data.country | string | País, ej. "Argentina" |
data.gender | string | "M" o "F" |
data.dial_code | string | Código de país, ej. "+54" |
data.phone_number | string | Teléfono sin código de país |
exp | number | Opcional. Si se envía, Nume lo ignora. |
Ejemplo de payload
Con email y datos de perfil:
{
"email": "usuario@ejemplo.com",
"full_name": "Juan Pérez",
"iat": 1710000000,
"data": {
"first_name": "Juan",
"last_name": "Pérez",
"dni": "12345678",
"date_of_birth": "1995-07-21T00:00:00.000Z",
"country": "Argentina",
"gender": "M",
"dial_code": "+54",
"phone_number": "1123456789"
}
}Mínimo con external_id:
{
"external_id": "USR-12345-ABC",
"iat": 1710000000
}Ejemplo de código (Node.js)
Importante
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const secret = process.env.NUME_SSO_JWT_SECRET; // secreto entregado por Nume
const integrationUuid = process.env.NUME_INTEGRATION_UUID; // integration UUID entregado por Nume
const apiBaseUrl = process.env.NUME_API_BASE_URL; // host de la API de Nume
app.get('/entrar-a-nume', (req, res) => {
const token = jwt.sign(
{
email: 'usuario@ejemplo.com',
full_name: 'Juan Pérez',
// iat lo agrega jsonwebtoken automáticamente
},
secret,
{ algorithm: 'HS256' },
);
const url =
`${apiBaseUrl}/integrations/sso/${integrationUuid}` +
`?token=${encodeURIComponent(token)}`;
res.redirect(url);
});
app.listen(3000);Errores comunes
Si el acceso falla, Nume redirige al usuario a una pantalla de error genérica (código en la URL). Códigos posibles:
| Código | Causa típica |
|---|---|
invalid_request | Falta identidad, o se enviaron email y external_id juntos |
invalid_token | JWT inválido, firma incorrecta o sin iat |
token_expired | iat con más de 5 minutos de antigüedad |
forbidden | Integración inactiva, empresa no habilitada para SSO, o empresa eliminada |
not_found | Integration UUID inexistente |
unexpected | Error inesperado al procesar el acceso |
Notas
- Si el usuario no existe, Nume lo crea.
- Si existía pero estaba desactivado, Nume lo reactiva al entrar por SSO.
- Si solo envían
external_id, Nume usa un email sintético interno basado en ese id. - Este flujo es independiente de
POST /integrations/token(API key).
Implementación con iframe (flujo embebido / nativo)
Si preferís no sacar al usuario de tu portal (o lo mostrás dentro de una app nativa con WebView), podés apuntar un iframe / WebView al mismo endpoint de tu backend que firma el JWT y hace el redirect (por ejemplo /entrar-a-nume).
Importante
Firmá el JWT siempre en tu backend. No expongas el secret en el frontend ni en la app.
Sin el atributo allow correcto no funcionan las llamadas con los médicos (cámara, micrófono y captura de pantalla).
El iframe carga tu endpoint; ese endpoint redirige a Nume
<iframe
title="Nume"
src="/entrar-a-nume"
style="width: 100%; height: 100%; border: 0;"
allow="camera *; microphone *; autoplay *; display-capture *; clipboard-read *; clipboard-write *"
allowfullscreen
></iframe>