Instalación de OAuth2 Proxy para Autenticación de Aplicaciones

OAuth2 Proxy es un proxy inverso que añade autenticación OAuth2 a cualquier aplicación web sin modificar su código fuente. Situado delante de la aplicación, intercepta todas las solicitudes y redirige a los usuarios no autenticados al proveedor de identidad elegido (Google, GitHub, Keycloak, Okta, etc.). Esta guía cubre la instalación, la configuración con los principales proveedores, la integración con Nginx y las políticas de control de acceso.

Requisitos Previos

  • Servidor Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
  • Nginx instalado y funcionando como proxy inverso
  • Dominio con SSL configurado (HTTPS obligatorio para OAuth2)
  • Acceso a un proveedor OAuth2 (Google, GitHub, Keycloak, etc.)
  • Acceso root o sudo

Instalación de OAuth2 Proxy

Instalación desde el binario oficial

# Descargar la última versión de oauth2-proxy
OAUTH2_PROXY_VERSION="7.6.0"
wget "https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v${OAUTH2_PROXY_VERSION}/oauth2-proxy-v${OAUTH2_PROXY_VERSION}.linux-amd64.tar.gz"

# Extraer e instalar el binario
tar -xzf "oauth2-proxy-v${OAUTH2_PROXY_VERSION}.linux-amd64.tar.gz"
sudo cp "oauth2-proxy-v${OAUTH2_PROXY_VERSION}.linux-amd64/oauth2-proxy" /usr/local/bin/oauth2-proxy
sudo chmod +x /usr/local/bin/oauth2-proxy

# Verificar la instalación
oauth2-proxy --version

Instalación con Docker

# Imagen oficial de oauth2-proxy
docker pull quay.io/oauth2-proxy/oauth2-proxy:latest
# Generar un secreto aleatorio para las cookies de sesión
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Guardar este valor como COOKIE_SECRET

Configuración con Google

Crear credenciales en Google Cloud Console

  1. Ve a console.cloud.google.com
  2. APIs & Services > Credentials > Create Credentials > OAuth 2.0 Client IDs
  3. Configura:
    • Application type: Web application
    • Authorized redirect URIs: https://app.tudominio.com/oauth2/callback
  4. Copia el Client ID y el Client Secret

Archivo de configuración

# Crear el directorio de configuración
sudo mkdir -p /etc/oauth2-proxy

cat > /etc/oauth2-proxy/oauth2-proxy.cfg << 'EOF'
# Proveedor de autenticación
provider = "google"
client_id = "TU_GOOGLE_CLIENT_ID.apps.googleusercontent.com"
client_secret = "TU_GOOGLE_CLIENT_SECRET"

# URL de la aplicación que vamos a proteger
upstreams = ["http://127.0.0.1:3000"]

# Dirección en la que escuchará oauth2-proxy
http_address = "127.0.0.1:4180"

# Cookie settings
cookie_secret = "TU_COOKIE_SECRET_GENERADO"
cookie_domains = [".tudominio.com"]
cookie_secure = true
cookie_httponly = true
cookie_samesite = "lax"
cookie_expire = "168h"  # 7 días

# URL de redirección tras autenticación
redirect_url = "https://app.tudominio.com/oauth2/callback"

# Control de acceso: solo emails de un dominio específico
email_domains = ["tuempresa.com"]

# O lista de emails autorizados
# authenticated_emails_file = "/etc/oauth2-proxy/emails.txt"

# Página de inicio de sesión
skip_provider_button = false

# Pasar headers de usuario a la aplicación protegida
pass_user_headers = true
pass_access_token = false
set_xauthrequest = true
EOF

Configuración con GitHub

Crear la OAuth App en GitHub

  1. Ve a GitHub > Settings > Developer settings > OAuth Apps > New OAuth App
  2. Configura:
    • Homepage URL: https://app.tudominio.com
    • Authorization callback URL: https://app.tudominio.com/oauth2/callback
  3. Genera y copia el Client Secret

Configuración para GitHub

cat > /etc/oauth2-proxy/oauth2-proxy.cfg << 'EOF'
provider = "github"
client_id = "TU_GITHUB_CLIENT_ID"
client_secret = "TU_GITHUB_CLIENT_SECRET"

upstreams = ["http://127.0.0.1:3000"]
http_address = "127.0.0.1:4180"
redirect_url = "https://app.tudominio.com/oauth2/callback"

cookie_secret = "TU_COOKIE_SECRET"
cookie_secure = true
cookie_httponly = true

# Restringir a una organización de GitHub
github_org = "mi-organizacion"

# O a un equipo específico de la organización
# github_team = "mi-organizacion/equipo-dev"

# O a usuarios específicos
# github_users = ["usuario1", "usuario2"]

email_domains = ["*"]
pass_user_headers = true
EOF

Configuración con Keycloak

# Obtener la configuración OIDC de Keycloak
# El endpoint de descubrimiento es:
# https://sso.tudominio.com/realms/empresa/.well-known/openid-configuration

cat > /etc/oauth2-proxy/oauth2-proxy.cfg << 'EOF'
provider = "keycloak-oidc"

# Credenciales del cliente Keycloak
client_id = "oauth2-proxy"
client_secret = "TU_KEYCLOAK_CLIENT_SECRET"

# URL del realm de Keycloak
oidc_issuer_url = "https://sso.tudominio.com/realms/empresa"

# Endpoints (se obtienen automáticamente del discovery si se usa oidc_issuer_url)

upstreams = ["http://127.0.0.1:3000"]
http_address = "127.0.0.1:4180"
redirect_url = "https://app.tudominio.com/oauth2/callback"

cookie_secret = "TU_COOKIE_SECRET"
cookie_secure = true
cookie_httponly = true
cookie_expire = "8h"

# Permitir todos los usuarios autenticados en Keycloak
email_domains = ["*"]

# O restringir a un rol específico de Keycloak
# allowed_roles = ["app-user"]
# allowed_groups = ["/mi-grupo"]

# Pasar el token de acceso a la aplicación
pass_access_token = true
pass_user_headers = true
set_xauthrequest = true

# Verificar el certificado SSL de Keycloak
ssl_insecure_skip_verify = false
EOF

Integración con Nginx

Método 1: OAuth2 Proxy como proxy completo

# /etc/nginx/sites-available/app-protegida
server {
    listen 443 ssl http2;
    server_name app.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/app.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.tudominio.com/privkey.pem;

    location / {
        # Redirigir todo el tráfico a oauth2-proxy
        # oauth2-proxy se encarga de autenticar y luego proxear a la app
        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-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Método 2: Nginx con subrequest de autenticación (auth_request)

Este método es más flexible: Nginx verifica la autenticación con oauth2-proxy pero el tráfico principal va directamente a la aplicación.

# /etc/nginx/sites-available/app-con-auth
server {
    listen 443 ssl http2;
    server_name app.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/app.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.tudominio.com/privkey.pem;

    # Endpoint interno de oauth2-proxy para verificar la autenticación
    location = /oauth2/auth {
        internal;
        proxy_pass http://127.0.0.1:4180;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header X-Original-Remote-Addr $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
    }

    # Rutas de oauth2-proxy (login, logout, callback)
    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-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Aplicación protegida
    location / {
        # Verificar la autenticación antes de pasar la solicitud
        auth_request /oauth2/auth;
        auth_request_set $auth_cookie $upstream_http_set_cookie;

        # Si no está autenticado, redirigir a la página de login
        error_page 401 = /oauth2/sign_in;

        # Pasar información del usuario a la aplicación
        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;

        # Proxy a la aplicación real
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
# Activar la configuración
sudo ln -s /etc/nginx/sites-available/app-con-auth /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Políticas de Acceso

Lista de emails autorizados

# Crear el archivo de emails autorizados
cat > /etc/oauth2-proxy/emails.txt << 'EOF'
[email protected]
[email protected]
[email protected]
[email protected]
EOF

# Referenciar en la configuración
# authenticated_emails_file = "/etc/oauth2-proxy/emails.txt"

Restricción por dominio de email

# Solo usuarios con email @empresa.com
email_domains = ["empresa.com"]

# Múltiples dominios
email_domains = ["empresa.com", "subsidiaria.com"]

# Cualquier email autenticado
email_domains = ["*"]

Excluir rutas del control de acceso

# En el archivo de configuración, rutas que no requieren autenticación
skip_auth_routes = ["GET=/api/public", "GET=/health", "GET=/robots.txt"]

# O usar prefijos
skip_auth_prefixes = ["/public/", "/assets/"]

Configurar como Servicio

# Crear el usuario del sistema para oauth2-proxy
sudo useradd -r -s /bin/false oauth2-proxy

# Crear el servicio systemd
sudo cat > /etc/systemd/system/oauth2-proxy.service << 'EOF'
[Unit]
Description=OAuth2 Proxy
After=network.target

[Service]
Type=simple
User=oauth2-proxy
Group=oauth2-proxy
ExecStart=/usr/local/bin/oauth2-proxy --config /etc/oauth2-proxy/oauth2-proxy.cfg
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable oauth2-proxy
sudo systemctl start oauth2-proxy

# Verificar el estado
sudo systemctl status oauth2-proxy
sudo journalctl -u oauth2-proxy -f

Solución de Problemas

Error: invalid cookie

# El cookie_secret debe tener exactamente 16, 24 o 32 bytes
python3 -c "import secrets; print(secrets.token_urlsafe(32))"

# Verificar en los logs
sudo journalctl -u oauth2-proxy -n 20

Error: redirect_uri_mismatch

La URL de callback registrada en el proveedor no coincide con la configurada en oauth2-proxy.

# Verificar que coinciden exactamente (incluyendo http/https y trailing slash)
# En el proveedor: https://app.tudominio.com/oauth2/callback
# En oauth2-proxy: redirect_url = "https://app.tudominio.com/oauth2/callback"

Los usuarios son redirigidos en bucle

# Verificar que las rutas /oauth2/ no requieren autenticación en Nginx
# La directiva auth_request no debe aplicarse a /oauth2/

# Verificar que Nginx pasa correctamente las cookies
grep -A5 "location /oauth2/" /etc/nginx/sites-available/app-con-auth

Error de SSL al conectar con el proveedor

# Para entornos de desarrollo con certificados autofirmados
ssl_insecure_skip_verify = true  # Solo para pruebas, nunca en producción

# En producción, añadir el certificado CA al almacén de confianza del sistema
sudo cp mi-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

Conclusión

OAuth2 Proxy es la solución más rápida para añadir autenticación empresarial a cualquier aplicación web sin modificar su código. La combinación con Nginx usando auth_request permite proteger aplicaciones internas, paneles de administración y herramientas de desarrollo con las credenciales corporativas de Google Workspace, GitHub, Keycloak o cualquier proveedor OAuth2, añadiendo una capa de seguridad robusta en minutos.