7.6 KiB
Prompt: SSO OIDC + Forward Auth — Diagnostico y alternativas
Contexto
Proyecto en /home/felidae/Portainer_repo/. Infraestructura Docker Compose con:
- Traefik v3.6.13 como reverse proxy (red
proxy) - Authentik como SSO via Forward Auth (
ths-authentik@docker) - CrowdSec como IPS/IDS via plugin Traefik (
crowdsec-bouncer@file) - Homepage como dashboard (descubre labels Docker)
Se han levantado dos nuevos servicios que necesitan SSO con Authentik + enlaces compartidos publicos (sin login):
| Servicio | Dominio | Imagen |
|---|---|---|
| OpenGist | opengist.sherlockhomeless.net |
ghcr.io/thomiceli/opengist:latest (puerto 6157) |
| OneTimeSecret | ots.sherlockhomeless.net |
onetimesecret/onetimesecret:latest (puerto 3000, necesita Redis) |
Que funciona
- DNS: registros A creados con
cloudflared/add-domain.shapuntando a193.70.84.224 - Traefik: rutas TLS con Let's Encrypt para ambos dominios
- CrowdSec: bouncer activo, bloqueando IPs en todos los routers
- Forward Auth: redirige a Authentik al visitar las URLs raiz (302 a
/application/o/authorize/) - Enlaces compartidos publicos: las rutas de gist (
/{user}/{gist}) y secretos (/secret/*,/private/*) evitan Authentik correctamente - Callbacks OIDC: las rutas
/auth/*(OTS) y/oauth/*(OpenGist) evitan Authentik, llegan al backend - Homepage: labels Docker puestos, descubre ambos servicios
Routers Traefik configurados
OpenGist (opengist/docker-compose.yml):
Router 1 (prio 20, SIN Authentik):
Host(opengist.sherlockhomeless.net) && (PathRegexp(^/[a-z...]+/[a-z0-9]+) || PathPrefix(/oauth/))
→ crowdsec-bouncer@file
Router 2 (prio 10, CON Authentik):
Host(opengist.sherlockhomeless.net)
→ crowdsec-bouncer@file, ths-authentik@docker
OTS (onetimesecret/docker-compose.yml):
Router 1 (prio 20, SIN Authentik):
Host(ots.sherlockhomeless.net) && (PathPrefix(/secret/) || PathPrefix(/private/) || PathPrefix(/auth/))
→ crowdsec-bouncer@file
Router 2 (prio 10, CON Authentik):
Host(ots.sherlockhomeless.net)
→ crowdsec-bouncer@file, ths-authentik@docker
Donde se rompe
Problema principal
El usuario visita la URL, Authentik pide login (Forward Auth funciona), pero tras autenticarse en Authentik la app no reconoce al usuario como logueado. La app muestra su propio formulario/boton de login.
La causa raiz es la diferencia entre Forward Auth y reconocimiento de sesion dentro de la app:
- Forward Auth: protege la RUTA a nivel HTTP. Authentik verifica si la
peticion tiene sesion valida. Si no, redirige al login. Si si, deja pasar
la peticion y añade headers (
X-Authentik-Username, etc.). - La app: tiene su propio sistema de sesiones. No sabe leer los headers
X-Authentik-*. Necesita su propio flujo OIDC/OAuth para crear una sesion interna.
Para cerrar ese gap se configuro OIDC en ambos servicios apuntando a Authentik:
| App | OIDC Provider (Authentik) | Redirect URI | Config en la app |
|---|---|---|---|
| OpenGist | pk=45, client_id=MZb3LrTP... |
/oauth/callback |
OG_OIDC_CLIENT_ID, OG_OIDC_CLIENT_SECRET, OG_OIDC_ISSUER |
| OTS | pk=46, client_id=Bqd0erWf... |
/auth/oidc/callback |
OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_ISSUER, AUTH_SSO_ENABLED=true, AUTHENTICATION_MODE=full, AUTH_SECRET=... |
Sintoma actual reportado por el usuario
En https://ots.sherlockhomeless.net/signin aparece el boton "Sign in with
Authentik". Al hacer clic estando ya logueado en Authentik, no cambia nada,
sigue pidiendo sign in. El flujo OIDC aparentemente no completa la creacion
de sesion en OTS.
Posibles causas:
- La cookie de sesion de Authentik no se envia en el callback (problema de dominio/cookie SameSite)
- El callback OIDC falla en OTS (error de configuracion Rodauth/OmniAuth)
- Forward Auth interfiere en alguna parte del flujo (aunque las rutas de callback ya se excluyeron)
- La sesion de Authentik no persiste entre Forward Auth y OIDC
Otros detalles tecnicos
-
Authentik: el dominio es
auth.sherlockhomeless.net. Los providers OIDC usan issuer por provider (issuer_mode: per_provider). Issuer OpenGist:https://auth.sherlockhomeless.net/application/o/MZb3LrTP.../Issuer OTS:https://auth.sherlockhomeless.net/application/o/Bqd0erWf.../ -
OTS healthcheck: la imagen oficial tiene un healthcheck built-in (
bin/healthcheck.sh) que falla en nuestro entorno. Se deshabilito conhealthcheck: { disable: true }porque Traefik se niega a rutear contenedores unhealthy. -
OTS full auth: requiere
AUTH_SECRET(valor generado conopenssl rand -hex 48), SQLite en/app/data/auth.db(montado en/opt/onetimesecret/data:Z, uid 1001), y Redis para los datos de la app. -
OpenGist: usa
OG_OPENGIST_HOME=/opengistcon SQLite interno. No requiere base de datos externa.
Archivos clave
Portainer_repo/
├── opengist/
│ ├── docker-compose.yml
│ └── .env
├── onetimesecret/
│ ├── docker-compose.yml
│ └── .env
├── authentik/
│ ├── docker-compose.yml
│ ├── create-auth-app.sh
│ └── .env
├── Traefik/docker-compose.yml
├── crowdsec/docker-compose.yml
├── cloudflared/
│ ├── add-domain.sh
│ └── .env
└── NUEVA-APP.md (guia de despliegue de nuevas apps)
Credenciales OIDC en Authentik
Obtenibles via API con token generado desde docker exec ths-authentik-server:
# OpenGist OIDC provider (pk=45)
curl -sk -H "Authorization: Bearer $TOKEN" \
https://auth.sherlockhomeless.net/api/v3/providers/oauth2/45/
# OTS OIDC provider (pk=46)
curl -sk -H "Authorization: Bearer $TOKEN" \
https://auth.sherlockhomeless.net/api/v3/providers/oauth2/46/
Objetivo para el siguiente agente
Conseguir que el flujo SSO funcione de extremo a extremo:
- Usuario visita
https://opengist.sherlockhomeless.net/ohttps://ots.sherlockhomeless.net/ - Authentik muestra su pagina de login (Forward Auth) — esto YA funciona
- Usuario se autentica en Authentik
- Al volver a la app, el usuario aparece logueado automaticamente (la app reconoce al usuario via OIDC sin requerir clic extra)
- Los enlaces compartidos (
/{user}/{gist},/secret/*) siguen siendo publicos (sin login) — esto YA funciona
Ideas a explorar
-
Alternativa A — Quitar Forward Auth, usar solo OIDC: si las apps soportan auto-redirect al provider OIDC cuando no hay sesion, se elimina la doble autenticacion. El login seria "clic en boton" en vez de "automatico al entrar", pero el SSO seria mas limpio.
-
Alternativa B — Authentik en modo proxy (no forward auth): configurar Authentik como reverse proxy real en vez de forward auth. Authentik manejaria todo el flujo OIDC y pasaria el usuario autenticado al backend.
-
Alternativa C — Header auth nativo: investigar si OpenGist u OTS soportan autenticacion por headers de proxy inverso (tipo
Remote-User). Si es asi, se puede usar solo Forward Auth sin OIDC, pasando el headerX-Authentik-UsernamecomoRemote-User. -
Alternativa D — Autentik OAuth2 en vez de OIDC: probar si el flujo OAuth2 simple (sin OpenID Connect) funciona mejor con estas apps.
-
Alternativa E — Debug del flujo OIDC actual: revisar logs de OTS (
docker logs onetimesecret) y de Authentik durante el flujo OIDC para identificar exactamente donde falla el callback. Puede ser un problema de SameSite cookie, CORS, o redirect_uri mismatch.