SSO para cualquier app con oauth2-proxy y reverse proxy
Protege una app sin login con OIDC usando oauth2-proxy y forward auth en nginx o Traefik. Evita errores 401, bucles de redirección y problemas de cookies.
Autenticación delegada: cómo proporcionar SSO a una aplicación sin inicio de sesión
oauth2-proxy proporciona inicio de sesión único a una aplicación que no tiene su propio sistema de inicio de sesión. Funciona porque el reverse proxy situado delante de la aplicación detiene todas las peticiones, pregunta a oauth2-proxy si la petición contiene una sesión válida y sólo la reenvía al backend cuando la respuesta es afirmativa. El código de la aplicación no cambia porque la aplicación nunca ve esta comprobación.
La comprobación añade una petición HTTP. El proxy envía una copia de las cabeceras de la petición entrante a /oauth2/auth y lee el código de estado. Un 202 significa que el cliente tiene una sesión, por lo que el proxy reenvía la petición original a la aplicación. Un 401 significa que no hay sesión, por lo que el proxy redirige el navegador a /oauth2/sign_in. Este endpoint inicia un inicio de sesión OpenID Connect (OIDC) en el proveedor de identidad. OIDC es la capa de identidad que se ejecuta sobre OAuth 2.0. El proveedor es el sistema que ya utiliza para los inicios de sesión.
Este patrón tiene un nombre en cada reverse proxy. Nginx llama a la directiva auth_request. Traefik llama middleware a forwardAuth. Caddy lo escribe forward_auth. El servicio que responde a la subpetición también puede sustituirse. oauth2-proxy es la opción habitual porque utiliza OIDC directamente y no necesita su propia base de datos.
Dibuje el límite de confianza antes de escribir cualquier configuración
Tras una comprobación correcta, oauth2-proxy devuelve la identidad en las cabeceras de respuesta y el proxy inverso las copia en la solicitud al backend. Con set_xauthrequest habilitado, obtiene X-Auth-Request-User y X-Auth-Request-Email. La aplicación lee esas cabeceras y confía en ellas.
Ese es todo el modelo de seguridad, así que indique claramente la consecuencia. Cualquier proceso que pueda abrir una conexión TCP al puerto de la aplicación puede establecer esas cabeceras por su cuenta y hacerse pasar por cualquier usuario. Un solo curl -H "X-Auth-Request-Email: admin@example.com" http://app-host:3000/ supone un bypass completo si llega directamente a la aplicación.
Por tanto, la aplicación no debe ser accesible salvo a través del proxy. En Docker Compose, elimine la asignación ports: del servicio de la aplicación y déjelo en la red interna, de modo que sólo el contenedor del proxy pueda conectarse a él. En un host independiente, vincule la aplicación a 127.0.0.1:3000 en lugar de 0.0.0.0:3000. Después, compruebe qué ha expuesto realmente:
sudo ss -tlnp | grep 3000Una línea que indique 0.0.0.0:3000 significa que la aplicación responde en la IP pública y que su control de acceso es sólo decorativo. 127.0.0.1:3000 es lo que necesita. Una regla de firewall es una segunda capa útil, pero la dirección de enlace es la que seguirá vigente si otra herramienta vacía el conjunto de reglas.
Instalar oauth2-proxy
En agosto de 2026, la versión actual es v7.15.3, publicada en junio de 2026. Instale el binario y verifique la descarga:
cd /tmp
curl -fsSLO https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.15.3/oauth2-proxy-v7.15.3.linux-amd64.tar.gz
curl -fsSLO https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.15.3/oauth2-proxy-v7.15.3.linux-amd64.tar.gz-sha256sum.txt
sha256sum -c oauth2-proxy-v7.15.3.linux-amd64.tar.gz-sha256sum.txt
tar -xzf oauth2-proxy-v7.15.3.linux-amd64.tar.gz
sudo install -m 755 oauth2-proxy-v7.15.3.linux-amd64/oauth2-proxy /usr/local/bin/oauth2-proxy
oauth2-proxy --versionsha256sum -c debe mostrar una línea que termine en OK. Si muestra FAILED, deténgase y vuelva a descargarlo en lugar de ejecutar el binario.
En Docker, la imagen es quay.io/oauth2-proxy/oauth2-proxy y debe fijar la etiqueta: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3. Dejarla en latest convierte una docker compose pull rutinaria en una actualización no planificada del único proceso que protege todas las aplicaciones del servidor.
Generar el secreto de la cookie
La cookie de sesión está cifrada y cookie_secret es la clave. Debe tener exactamente 16, 24 o 32 bytes porque se convierte en una clave AES (estándar de cifrado avanzado). Con cualquier otra longitud, oauth2-proxy se niega a iniciar y muestra un error de arranque que identifica el secreto de la cookie.
openssl rand -base64 32 | tr -- '+/' '-_'tr no es un elemento estético. Convierte base64 estándar en el alfabeto compatible con URL, de modo que el valor pueda pasar por un shell, un archivo de entorno y una cabecera HTTP sin problemas de comillas.
Aplique dos reglas a este valor. Use un secreto diferente para cada despliegue. Si ejecuta más de una instancia de oauth2-proxy detrás del mismo dominio, asígneles a todas el mismo secreto, porque una cookie cifrada por una instancia debe poder ser leída por las demás.
Escriba la configuración de oauth2-proxy
Mantenga la configuración en un archivo en lugar de usar una línea de comandos extensa. Así, el secreto del cliente nunca aparece en la salida de ps.
# /etc/oauth2-proxy/oauth2-proxy.cfg
http_address = "127.0.0.1:4180"
reverse_proxy = true
provider = "oidc"
oidc_issuer_url = "https://id.example.com/application/o/myapp/"
client_id = "REPLACE_ME"
client_secret = "REPLACE_ME"
redirect_url = "https://app.example.com/oauth2/callback"
cookie_secret = "REPLACE_ME"
cookie_secure = true
cookie_domains = [".example.com"]
whitelist_domains = [".example.com"]
email_domains = ["*"]
set_xauthrequest = true
upstreams = ["static://202"]reverse_proxy = true indica a oauth2-proxy que confíe en las cabeceras X-Forwarded-* del proxy situado delante. Sin esta opción, oauth2-proxy considera que la dirección del cliente es la dirección del propio proxy y puede determinar incorrectamente si la solicitud llegó mediante HTTPS.
upstreams = ["static://202"] hace que oauth2-proxy responda con 202 a una solicitud autenticada sin enviar contenido al proxy. Esto es exactamente lo que necesita forward auth, porque el proxy inverso se encarga de reenviar la solicitud. La otra arquitectura coloca oauth2-proxy directamente en la ruta de la solicitud mediante upstreams = ["http://127.0.0.1:3000"] y sin auth_request. Es más sencilla para una aplicación, pero no escala a diez.
email_domains = ["*"] permite cualquier dirección que su proveedor autentique. Limítelo a su propio dominio o, mejor aún, restrinja el acceso mediante una vinculación de grupo en el proveedor, porque es allí donde ya administra los usuarios.
Ejecútelo con systemd mediante un usuario propio:
# /etc/systemd/system/oauth2-proxy.service
[Unit]
Description=oauth2-proxy
After=network-online.target
Wants=network-online.target
[Service]
User=oauth2-proxy
Group=oauth2-proxy
ExecStart=/usr/local/bin/oauth2-proxy --config=/etc/oauth2-proxy/oauth2-proxy.cfg
Restart=on-failure
ProtectSystem=strict
PrivateTmp=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.targetsudo useradd --system --no-create-home --shell /usr/sbin/nologin oauth2-proxy
sudo install -d -m 750 /etc/oauth2-proxy
sudo chown -R oauth2-proxy:oauth2-proxy /etc/oauth2-proxy
sudo chmod 600 /etc/oauth2-proxy/oauth2-proxy.cfg
sudo systemctl daemon-reload
sudo systemctl enable --now oauth2-proxy
curl -s http://127.0.0.1:4180/ping/ping que muestra OK indica que el proceso se inició y cargó su configuración. Es el endpoint de estado propio de oauth2-proxy y nunca solicita una sesión. Si no responde, revise journalctl -u oauth2-proxy -n 50, porque una URL de issuer incorrecta y un secreto de cookie con una longitud incorrecta provocan un error durante el inicio y ambos casos se indican en los mensajes.
Registre la URI de redirección con su proveedor
Cree una aplicación OIDC en su proveedor y establezca su URI de redirección exactamente en redirect_url de la configuración: https://app.example.com/oauth2/callback. Exactamente significa que el esquema, el host, el puerto y la ruta deben coincidir carácter por carácter. Una barra final convierte la URI en otra distinta.
Este es el fallo más común de toda la configuración y se produce antes de que intervenga oauth2-proxy. El proveedor rechaza la solicitud de autorización y muestra su propia página de error, por lo que no aparece nada en el registro de oauth2-proxy. La señal está en la barra de direcciones: el navegador sigue en el dominio del proveedor y la cadena de consulta contiene error=invalid_request o la página muestra directamente redirect_uri. Cuando ocurra, corrija el registro de la aplicación en el proveedor, no la configuración del proxy.
Copie la URL del issuer desde el proveedor en lugar de escribirla manualmente. oauth2-proxy añade /.well-known/openid-configuration a oidc_issuer_url y obtiene ese documento de descubrimiento al iniciar. Compruébelo primero:
curl -s https://id.example.com/application/o/myapp/.well-known/openid-configuration | head -c 400Un JSON que contenga una clave authorization_endpoint indica que la URL del issuer es correcta. Un 404 o una página de error HTML indican que es incorrecta, y oauth2-proxy no podrá iniciarse con ese mismo 404. Si aún no ha elegido un proveedor, la comparación entre Keycloak, Authentik y Zitadel explica las diferencias, y la ejecución de Authentik como servidor SSO propio detalla la parte del proveedor de esta misma configuración.
Nginx: auth_request
Nginx realiza la autenticación delegada con auth_request, que ejecuta una subsolicitud interna y toma una decisión según su código de estado.
# in the http context, next to your other maps
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name app.example.com;
location /oauth2/ {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location = /oauth2/auth {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location / {
auth_request /oauth2/auth;
error_page 401 = @oauth2_signin;
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location @oauth2_signin {
return 302 /oauth2/sign_in?rd=$scheme://$host$request_uri;
}
}Hay tres detalles importantes. proxy_pass_request_body off con un Content-Length vacío evita que nginx copie el cuerpo de cada POST en la subsolicitud. Esto es importante porque oauth2-proxy no lee ese cuerpo. En una carga de archivos, la configuración predeterminada envía el archivo dos veces.
El par auth_request_set $auth_cookie y add_header Set-Cookie devuelve una cookie de sesión renovada al navegador. Si se omite, cookie_refresh no hace nada de forma silenciosa porque nginx descarta Set-Cookie de la subsolicitud y el navegador conserva el valor anterior hasta que caduque la sesión.
error_page 401 = @oauth2_signin convierte una comprobación fallida en un inicio de sesión. Sin ella, un visitante no autenticado recibe una página 401 Authorization Required sin ninguna forma de continuar.
Pruebe siempre antes de recargar:
sudo nginx -t && sudo systemctl reload nginxSi no conoce las directivas circundantes, la estructura de una configuración de reverse proxy de nginx explica la capa subyacente.
Traefik: middleware forwardAuth
Traefik necesita dos middlewares para esta tarea. Uno ejecuta la comprobación. El otro convierte el código 401 en una redirección del navegador.
# dynamic configuration
http:
middlewares:
oauth-auth:
forwardAuth:
address: https://oauth.example.com/oauth2/auth
trustForwardHeader: true
oauth-errors:
errors:
status:
- "401-403"
service: oauth-backend
query: "/oauth2/sign_in?rd={url}"
statusRewrites:
"401": 302Asocie ambos al router que publica su aplicación y publique oauth2-proxy en su propio router en oauth.example.com, porque el navegador debe acceder a /oauth2/sign_in y /oauth2/callback sin pasar por la comprobación.
statusRewrites, que asigna 401 a 302, es la parte que suele omitirse. Sin esto, Traefik devuelve la redirección de inicio de sesión con un estado 401, el navegador no la sigue y el visitante ve una página que contiene una sola palabra: Found.
trustForwardHeader: true pasa el host y el URI originales a oauth2-proxy. oauth2-proxy los necesita para construir el valor rd, que devuelve al usuario a la página solicitada. Configure whitelist_domains para incluir también ese host. De lo contrario, oauth2-proxy descarta el parámetro rd por considerarlo un riesgo de redirección abierta y todos terminan en / después de iniciar sesión. Un servidor Traefik suele publicar varias aplicaciones a la vez. Enrutar varias aplicaciones de Docker Compose mediante una sola instancia de Traefik muestra la estructura de routers que se integra aquí.
Caddy: forward_auth
app.example.com {
handle /oauth2/* {
reverse_proxy oauth2-proxy.internal:4180 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Uri {uri}
}
}
handle {
forward_auth oauth2-proxy.internal:4180 {
uri /oauth2/auth
header_up X-Real-IP {remote_host}
copy_headers X-Auth-Request-User X-Auth-Request-Email
@error status 401
handle_response @error {
redir * /oauth2/sign_in?rd={scheme}://{host}{uri}
}
}
reverse_proxy upstream.internal:3000
}
}El orden es importante. El bloque /oauth2/* va primero y no incluye forward_auth, porque un visitante que no ha iniciado sesión debe poder acceder a las rutas de inicio de sesión y de callback. Coloque la comprobación delante de esas rutas. De lo contrario, el inicio de sesión se redirige a sí mismo hasta que el navegador abandona.
copy_headers es lo que transfiere la identidad a la solicitud del upstream, y sólo genera valores cuando oauth2-proxy se ejecuta con set_xauthrequest = true. Elegir entre los proxies es una cuestión independiente, y la comparación de nginx, Caddy y Traefik la explica.
¿Por qué el inicio de sesión vuelve a mostrar la página de acceso?
Inicia sesión en el proveedor, este te redirige de vuelta y oauth2-proxy te envía directamente al proveedor otra vez. El bucle indica que la solicitud de callback llegó sin la cookie que oauth2-proxy estableció al iniciar el flujo. El registro identifica el caso:
No cookies were found in OAuth callback.o, cuando llegó alguna otra cookie pero no la correcta:
Cookies were found in OAuth callback, but none was a CSRF cookie.CSRF significa falsificación de solicitudes entre sitios. Esta cookie permite asociar un callback con el inicio de sesión que lo originó. El navegador muestra el mismo fallo como:
Login Failed: Unable to find a valid CSRF token. Please try again.Comprueba estas cuatro causas en este orden.
cookie_secure = truemientras el navegador accedía al sitio mediante HTTP sin cifrar. Un navegador no almacena una cookie marcada comoSecureen un origenhttp://, por lo que nunca la vuelve a enviar. Termina TLS (transport layer security) correctamente o establececookie_secure = falsesólo durante las pruebas en localhost.- Un valor de
cookie_domainsque no incluye el nombre de host de la barra de direcciones..example.comincluyeapp.example.comy no tiene ningún efecto sobreapp.example.net. - El navegador está descartando la cookie. Una extensión de privacidad estricta o el bloqueo de cookies de terceros puede eliminar
_oauth2_proxy_csrfentre la redirección saliente y el callback. - Desfase del reloj. Si el reloj del servidor está muy desviado con respecto al del proveedor,
iatyexpdel token de ID quedan fuera de la ventana aceptada y la sesión se rechaza al llegar.timedatectldebería informarSystem clock synchronized: yes.
Obsérvalo desde el servidor en lugar de intentar adivinar la causa:
sudo journalctl -u oauth2-proxy -fCarga la aplicación en una ventana privada. Cada solicitud se registra con su estado, de modo que un callback seguido inmediatamente por otra redirección al proveedor confirma el bucle en el registro.
Rutas que deben omitir el inicio de sesión: API, webhooks y websockets
La autenticación mediante proxy supone que el navegador tiene una cookie. Los clientes que no usan un navegador fallan.
Un cliente de API que envía Authorization: Bearer <token> no tiene ninguna cookie. Por eso recibe una respuesta 302 hacia la página de inicio de sesión del proveedor y después intenta interpretar HTML como JSON. Hay dos soluciones sencillas. Si establece skip_jwt_bearer_tokens = true, oauth2-proxy acepta un token bearer JWT (JSON web token) válido del mismo emisor. Esto es adecuado cuando los clientes de la API ya obtienen sus tokens del proveedor. De lo contrario, excluya la ruta:
skip_auth_routes = [
"^/api/",
"POST=^/webhook/",
"GET=^/healthz$"
]Cada valor es una expresión regular que se compara con la ruta normalizada. De forma opcional, puede llevar delante un método HTTP y =. POST=^/webhook/ deja abierto el receptor del webhook a POST, mientras que una persona que acceda a la misma ruta desde un navegador sigue pasando por el inicio de sesión. Cada entrada crea un hueco en la protección. Por tanto, ancle las expresiones con ^ y manténgalas tan limitadas como permita el cliente.
Los websockets son el caso que suele configurarse mal. La solicitud de actualización es una solicitud HTTP GET normal que lleva las mismas cookies que cualquier otra solicitud. Por eso pasa la comprobación normalmente y no necesita ninguna exclusión. El problema está en el proxy que la gestiona. Sin las cabeceras Upgrade y Connection en la ubicación protegida, la actualización no se completa y el cliente de la aplicación reintenta indefinidamente, mostrando un mensaje WebSocket connection ... failed en la consola del navegador. Excluir la ruta no soluciona este problema, porque la solicitud ya estaba autorizada.
Sí existe una limitación importante. La comprobación se ejecuta una sola vez, durante la actualización. Un websocket que permanece abierto durante horas no se vuelve a comprobar. Por tanto, eliminar a un usuario del proveedor no cierra el socket que ya tiene abierto. Reinicie la aplicación para cortar las conexiones activas.
Almacenamiento de sesiones y una cookie que crece demasiado
De forma predeterminada, toda la sesión se almacena dentro de la cookie y se cifra con su cookie_secret. Esto permite que oauth2-proxy no mantenga estado y evita depender de otro servicio. También tiene un límite, porque los navegadores restringen el tamaño de las cookies a aproximadamente 4 KB. Cuando el token de identidad contiene una lista larga de grupos, oauth2-proxy divide la sesión entre _oauth2_proxy_0, _oauth2_proxy_1 y las partes siguientes. Después de unas pocas partes, las cabeceras de la solicitud crecen lo suficiente para que nginx responda con 400 Request Header Or Cookie Too Large antes de que la aplicación reciba la solicitud.
Cuando ocurra esto, mueva la sesión al servidor:
session_store_type = "redis"
redis_connection_url = "redis://127.0.0.1:6379"El navegador sólo conserva un ticket corto y la sesión cifrada se almacena en Redis. El coste es que debe mantener activo otro servicio: si Redis deja de funcionar, todas las sesiones dejan de ser válidas y todos los usuarios cierran sesión al mismo tiempo. El almacén de cookies también tiene un coste: dos solicitudes que actualicen la misma sesión exactamente al mismo tiempo pueden entrar en conflicto y obligar a iniciar sesión de nuevo.
Qué no proporciona la autenticación delegada
Esta función actúa como una barrera de acceso. No proporciona autorización dentro de la aplicación, y esa diferencia determina si este enfoque se adapta a su caso.
Una vez que un usuario atraviesa la barrera, la aplicación ve lo mismo que veía antes. Si la aplicación tiene sus propios roles, la autenticación delegada no los asigna, salvo que la aplicación admita autenticación basada en cabeceras y asocie una cabecera con una cuenta. Grafana sí lo hace mediante sus opciones de configuración auth.proxy. La mayoría de las aplicaciones autoalojadas no lo hacen. Por tanto, todas las personas que atraviesan la barrera representan la misma identidad única para la aplicación, y esa identidad suele tener permisos de administrador.
Tampoco protege los tokens de API propios de la aplicación. Un token de acceso personal emitido por la aplicación autentica directamente en la aplicación, no en oauth2-proxy. Por eso, el token deja de funcionar en cuanto la barrera se coloca delante. Si excluye la ruta de la API para recuperarlo, ese token pasa a ser la única protección de la ruta. Ahora ejecuta dos sistemas de autenticación en un mismo servicio, y el inicio de sesión único sólo cubre uno de ellos.
La revocación es la tercera limitación. Eliminar un usuario del proveedor impide nuevos inicios de sesión y detiene la renovación del token que realiza cookie_refresh, pero una cookie de sesión existente sigue siendo válida hasta que caduca. cookie_expire tiene un valor predeterminado de 168 horas, lo que equivale a una semana de acceso para alguien que acaba de eliminar. Establezca cookie_refresh en un valor corto, como una hora, para que la revocación se aplique dentro de ese intervalo.
El registro de auditoría también termina en la barrera. oauth2-proxy registra quién atravesó la barrera y cuándo. La aplicación registra una sesión sin nombre. Si necesita responder a la pregunta de quién cambió una configuración, la identidad mediante cabeceras en la aplicación es el requisito mínimo. Las cuentas independientes por usuario son la opción correcta.
Cuándo pagar por SSO es la mejor opción
La autenticación delegada es la herramienta adecuada cuando una aplicación no tiene ningún inicio de sesión o usa una contraseña compartida, y quiere disponer de un único lugar para añadir y eliminar usuarios. Requiere una tarde de trabajo y un proceso adicional, y funciona con cualquier aplicación que se comunique mediante HTTP.
Es la herramienta equivocada cuando distintas personas necesitan permisos diferentes dentro de la misma aplicación. Una puerta de acceso no puede expresar «Ana puede editar los paneles y Bo sólo puede leerlos». Si el proveedor ofrece un nivel con SSO, la asignación de grupos a roles suele ser precisamente lo que está comprando. Recrearla mediante cabeceras y reglas del proxy es más frágil que pagar por ella. Vale la pena leer El patrón de precios de esos niveles con SSO antes de decidir.
Otras dos situaciones apuntan en la misma dirección. Una auditoría de cumplimiento que necesite registros por usuario dentro de la aplicación no aceptará un registro de acceso del proxy como evidencia. Además, cualquier aplicación con un cliente móvil o de escritorio que no envíe cookies del navegador tendrá problemas con la puerta de acceso en cada solicitud.
FAQ
¿Qué es la autenticación delegada?
La autenticación delegada es un patrón en el que el reverse proxy consulta a un servicio de autenticación independiente sobre cada petición entrante antes de enviarla al upstream. El proxy envía las cabeceras de la petición a un endpoint como /oauth2/auth y lee el código de estado. 202 significa que la petición está autorizada, por lo que la petición original continúa hasta la aplicación. 401 significa que no hay ninguna sesión, por lo que el proxy redirige el navegador al inicio de sesión. Nginx lo implementa con la directiva auth_request, Traefik con el middleware forwardAuth y Caddy con forward_auth.
¿Por qué oauth2-proxy me redirige a la página de inicio de sesión en un bucle?
La petición de callback llegó a oauth2-proxy sin su cookie CSRF, por lo que oauth2-proxy reinicia el flujo. El registro del servidor muestra No cookies were found in OAuth callback. y el navegador muestra Login Failed: Unable to find a valid CSRF token. Please try again.. La causa habitual es cookie_secure = true en un sitio al que el navegador llegó mediante HTTP sin cifrar, porque un navegador no almacena una cookie Secure en un origen http://. La siguiente causa más frecuente es un valor cookie_domains que no incluye el hostname mostrado en la barra de direcciones.
¿Cómo permito que un cliente API o un webhook atraviese oauth2-proxy?
Use skip_auth_routes con una expresión regular anclada y, opcionalmente, limítela a un método HTTP, por ejemplo POST=^/webhook/. Si sus clientes API ya tienen JWT emitidos por el mismo proveedor, skip_jwt_bearer_tokens = true acepta esos tokens en lugar de una cookie y mantiene protegida la ruta. Todo lo incluido en skip_auth_routes queda sin autenticación para todos, así que mantenga cada expresión tan limitada como permita el emisor.
¿Proporciona oauth2-proxy permisos por usuario a la aplicación?
No. Es una puerta de acceso, no un sistema de autorización. Decide quién llega a la aplicación, y todas las personas que llegan parecen idénticas para la aplicación, a menos que esta lea las cabeceras de identidad y las asocie a cuentas. Grafana puede hacerlo mediante su configuración auth.proxy. La mayoría de las aplicaciones autoalojadas no puede, por lo que todas las personas que superan la puerta comparten la misma identidad con la que se ejecuta la aplicación.
¿Alguien puede omitir oauth2-proxy estableciendo la cabecera de identidad por su cuenta?
Sí, si puede acceder directamente a la aplicación. La identidad llega como una cabecera normal, como X-Auth-Request-Email, y la aplicación confía en lo que recibe. Cualquiera que pueda abrir una conexión al puerto de la aplicación puede enviar esa cabecera y asumir la identidad de cualquier usuario. Enlace la aplicación a 127.0.0.1 o manténgala en una red Docker interna sin ningún puerto publicado, y confírmelo con sudo ss -tlnp.