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.
Flujos soportados
Sección titulada «Flujos soportados»| 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. statees obligatorio y elredirect_uridebe coincidir en forma exacta.- PKCE está permitido (
S256yplain) pero no es obligatorio.
Obtener un token
Sección titulada «Obtener un token»curl -u TestClient:TestSecret \ https://servidor/api/db/cliente/token \ -d 'grant_type=password&username=usuario&password=clave&client_id=TestClient'TestClientyTestSecretson las credenciales del cliente OAuth registrado en la base (tablaoauth_clients), no las del usuario.grant_type=passwordenvía las credenciales del usuario final; conclient_credentialsno se envíanusernamenipassword.
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:
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 correctoopenid web offline_access rompe el password grant en silencioCon openid primero, Histrix pide un realm llamado openid, que ningún perfil
declara, y el login falla con credenciales válidas.
OpenID Connect
Sección titulada «OpenID Connect»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"]}Claves de firma
Sección titulada «Claves de firma»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.
Bloqueo de .well-known en el proxy
Sección titulada «Bloqueo de .well-known en el proxy»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.
Rutas sin autenticación
Sección titulada «Rutas sin autenticación»Dos casos no requieren token:
- XML públicos. Cualquier XML cuya ruta empiece con
public/se sirve sinAuthorization. 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.
Diagnóstico
Sección titulada «Diagnóstico»| 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 |