Ir al contenido

Autenticación y OIDC

La API de Histrix se autentica con OAuth 2.0. Cada base de datos es un emisor independiente: tiene sus propios clientes, sus propios usuarios y su propio par de claves de firma.

Grant type Uso
password Aplicaciones propias que piden usuario y contraseña
client_credentials Integraciones máquina a máquina, sin usuario
authorization_code Login delegado con OpenID Connect (con o sin PKCE)
refresh_token Renovación de un token de acceso vencido

Parámetros de configuración del servidor:

  • Vida del access token: 24 horas.
  • Vida del id_token: 1 hora.
  • Cada renovación emite un refresh token nuevo.
  • El flujo implícito está deshabilitado; solo authorization_code.
  • state es obligatorio y el redirect_uri debe coincidir en forma exacta.
  • PKCE está permitido (S256 y plain) pero no es obligatorio.
Ventana de terminal
curl -u TestClient:TestSecret \
https://servidor/api/db/cliente/token \
-d 'grant_type=password&username=usuario&password=clave&client_id=TestClient'
  • TestClient y TestSecret son las credenciales del cliente OAuth registrado en la base (tabla oauth_clients), no las del usuario.
  • grant_type=password envía las credenciales del usuario final; con client_credentials no se envían username ni password.

Respuesta:

{
"access_token": "f446bc61ebb06653cd86309f2e3f49b9481cf6a3",
"expires_in": 86400,
"token_type": "Bearer",
"scope": "web openid offline_access",
"refresh_token": "4e40020c4fd2c6ccd968ed69152b75bbb9460944"
}

El token se envía en todas las llamadas siguientes:

Ventana de terminal
curl --header "Authorization: Bearer f446bc61ebb06653cd86309f2e3f49b9481cf6a3" \
https://servidor/api/db/cliente/menu/

Realms: qué perfiles pueden entrar por cada canal

Sección titulada «Realms: qué perfiles pueden entrar por cada canal»

Un usuario no puede autenticarse por cualquier canal: su perfil declara en HTXPROFILES.realm la lista de realms habilitados, separados por coma. El login valida el realm pedido con FIND_IN_SET.

El realm que se exige en un password grant lo determina el cliente OAuth: es el primer valor del campo oauth_clients.scope. Si el cliente no tiene scope configurado, se usa web.

Por eso el orden del scope importa:

web openid offline_access correcto
openid web offline_access rompe el password grant en silencio

Con openid primero, Histrix pide un realm llamado openid, que ningún perfil declara, y el login falla con credenciales válidas.

Cada base publica sus endpoints de descubrimiento:

Método Ruta
GET /api/db/{db}/.well-known/openid-configuration
GET /api/db/{db}/.well-known/jwks.json
GET/POST /api/db/{db}/authorize
GET/POST /api/db/{db}/token
GET /api/db/{db}/userinfo

El issuer es {esquema}://{host}/api/db/{db}, y respeta X-Forwarded-Proto y X-Forwarded-Host cuando hay proxy inverso.

Respuesta del discovery:

{
"issuer": "https://servidor/api/db/cliente",
"authorization_endpoint": "https://servidor/api/db/cliente/authorize",
"token_endpoint": "https://servidor/api/db/cliente/token",
"userinfo_endpoint": "https://servidor/api/db/cliente/userinfo",
"jwks_uri": "https://servidor/api/db/cliente/.well-known/jwks.json",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials", "password"],
"id_token_signing_alg_values_supported": ["RS256"],
"scopes_supported": ["openid", "profile", "email"],
"claims_supported": ["sub", "name", "given_name", "family_name", "email"],
"token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"],
"code_challenge_methods_supported": ["S256", "plain"]
}

Los id_token se firman con RS256. Cada base tiene su propio par RSA de 2048 bits en database/.oidc/{db}/, generado de forma perezosa: un cliente que no usa OIDC nunca dispara la generación ni escribe en el filesystem.

Los endpoints de descubrimiento no están en la raíz del sitio sino bajo /api/db/{db}/. Varios proxies (Caddy, Nginx) traen reglas que solo permiten .well-known en la raíz y devuelven 403 en cualquier otra ubicación. Si el discovery o el JWKS fallan con 403, el problema está en el proxy.

Dos casos no requieren token:

  • XML públicos. Cualquier XML cuya ruta empiece con public/ se sirve sin Authorization. Es el mecanismo para publicar catálogos, galerías o endpoints de lectura hacia afuera.
  • Recursos por token de un solo uso. /api/db/{db}/pub/{token}, las encuestas y el circuito de registro y confirmación de usuarios.
Síntoma Causa habitual
401 con credenciales correctas oauth_clients.scope empieza con algo distinto de web, o el perfil no tiene ese realm en HTXPROFILES.realm
500 en todo login Falta la columna HTXPROFILES.realm
tree: [] con HTTP 200 en /menu/ El token no tiene usuario asociado: revisar parameters.login en la respuesta
500 en jwks.json o userinfo Propietario incorrecto de database/.oidc/{db}/
403 en .well-known/* Regla del proxy inverso
Menú vacío tras actualizar HTXMENU.web_version distinto de 1