Authelia: Gateway de Autenticación de Dos Factores

Authelia es un servidor de autenticación y autorización open source que actúa como gateway delante de tus aplicaciones, añadiendo autenticación de dos factores (TOTP, WebAuthn/FIDO2), SSO y control de acceso granular basado en reglas. A diferencia de oauth2-proxy, Authelia incluye su propia interfaz de login, gestión de usuarios y un sistema de reglas de acceso muy flexible que permite definir políticas diferentes para cada dominio o ruta. Esta guía cubre la instalación con Docker, la configuración de Nginx como proxy, TOTP y las reglas de control de acceso.

Requisitos Previos

  • Servidor Linux con Docker y Docker Compose
  • Nginx instalado como proxy inverso
  • Dominio con SSL (HTTPS obligatorio)
  • Certificados SSL válidos para el dominio y subdominios
  • Acceso root o sudo

Arquitectura de funcionamiento

Usuario
    │
    ▼
Nginx (Puerto 443)
    │ auth_request
    ▼
Authelia (Puerto 9091) ──────── Redis (sesiones)
    │                              └─ LDAP/archivo (usuarios)
    ▼
Aplicación protegida (Puerto 3000, 8080, etc.)

Instalación con Docker Compose

# Crear la estructura de directorios
mkdir -p /opt/authelia/{config,data}
cd /opt/authelia
# /opt/authelia/docker-compose.yml
services:
  authelia:
    image: authelia/authelia:latest
    container_name: authelia
    restart: unless-stopped
    volumes:
      - ./config:/config
      - ./data:/data
    ports:
      - "9091:9091"
    environment:
      TZ: Europe/Madrid
    networks:
      - authelia-net

  redis:
    image: redis:7-alpine
    container_name: authelia-redis
    restart: unless-stopped
    volumes:
      - redis-data:/data
    networks:
      - authelia-net

volumes:
  redis-data:

networks:
  authelia-net:
    driver: bridge
docker compose up -d

Configuración de Authelia

Archivo de configuración principal

cat > /opt/authelia/config/configuration.yml << 'EOF'
---
# Servidor
server:
  host: 0.0.0.0
  port: 9091
  path: ""

# Registro y auditoría
log:
  level: info
  format: text

# Dominio de SSO
default_redirection_url: https://auth.tudominio.com

# Tema de la interfaz de login
theme: light

# JWT para tokens de sesión (generar con: openssl rand -hex 32)
jwt_secret: "CAMBIA_ESTE_SECRETO_JWT_CON_OPENSSL_RAND"

# Autenticación de dos factores
totp:
  issuer: tudominio.com
  period: 30
  skew: 1

# WebAuthn (FIDO2/biometría)
webauthn:
  disable: false
  display_name: "Mi Dominio"
  attestation_conveyance_preference: indirect
  user_verification: preferred
  timeout: 60s

# Duración de la autenticación (tiempo hasta que caduca la sesión)
authentication_backend:
  password_reset:
    disable: false
  refresh_interval: 5m

  # Backend de usuarios: archivo local
  file:
    path: /config/users_database.yml
    watch: false
    search:
      email: false
      case_insensitive: false
    password:
      algorithm: argon2id
      argon2id:
        variant: argon2id
        iterations: 3
        memory: 65536
        parallelism: 4
        key_length: 32
        salt_length: 16

# Control de acceso
access_control:
  default_policy: deny
  rules:
    # Permitir acceso al endpoint de health sin autenticación
    - domain: auth.tudominio.com
      policy: bypass

    # Apps que requieren solo usuario y contraseña (1FA)
    - domain: blog.tudominio.com
      policy: one_factor

    # Apps críticas que requieren 2FA obligatorio
    - domain: panel.tudominio.com
      policy: two_factor

    - domain: "*.tudominio.com"
      policy: two_factor

# Sesiones
session:
  name: authelia_session
  secret: "CAMBIA_ESTE_SECRETO_SESSION"
  expiration: 1h
  inactivity: 30m
  remember_me: 1M
  cookies:
    - domain: tudominio.com
      authelia_url: https://auth.tudominio.com

# Redis para almacenamiento de sesiones (recomendado en producción)
storage:
  encryption_key: "CAMBIA_ESTE_SECRETO_STORAGE_32CHARS_MIN"
  local:
    path: /data/db.sqlite3

# Notificaciones (para reset de contraseña y registro de dispositivos 2FA)
notifier:
  # Para entornos de prueba, usar filesystem (escribe las notificaciones en un archivo)
  filesystem:
    filename: /data/notifications.txt

  # Para producción, usar SMTP
  # smtp:
  #   host: smtp.tudominio.com
  #   port: 587
  #   username: [email protected]
  #   password: "clave-smtp"
  #   sender: "Authelia <[email protected]>"
  #   tls:
  #     server_name: smtp.tudominio.com
EOF

Generar los secretos necesarios

# Generar el JWT secret
openssl rand -hex 32

# Generar el session secret
openssl rand -hex 32

# Generar el storage encryption key (mínimo 20 caracteres)
openssl rand -base64 32

# Actualizar los valores en configuration.yml con los generados

Integración con Nginx

Configuración del portal de autenticación

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

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

    location / {
        proxy_pass http://127.0.0.1:9091;
        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;
    }
}

Snippet de Nginx para la verificación de autenticación

# Crear snippets de Nginx reutilizables
sudo mkdir -p /etc/nginx/snippets/

cat > /etc/nginx/snippets/authelia-authrequest.conf << 'EOF'
# Endpoint interno de Authelia para verificar la autenticación
location = /internal/authelia/authz {
    internal;
    proxy_pass http://127.0.0.1:9091/api/authz/auth-request;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";

    proxy_set_header X-Original-Method $request_method;
    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
}
EOF

cat > /etc/nginx/snippets/authelia-location.conf << 'EOF'
# Verificar autenticación en cada solicitud
auth_request /internal/authelia/authz;
auth_request_set $target_url $scheme://$http_host$request_uri;

# En caso de no autenticado, redirigir al portal de Authelia
error_page 401 =302 https://auth.tudominio.com/?rd=$target_url;

# Pasar información del usuario autenticado a la aplicación
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $emails $upstream_http_remote_email;

proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $emails;
EOF

Proteger una aplicación con Authelia

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

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

    # Incluir el snippet de verificación
    include /etc/nginx/snippets/authelia-authrequest.conf;

    location / {
        # Verificar autenticación (2FA según las reglas de Authelia)
        include /etc/nginx/snippets/authelia-location.conf;

        # 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;
    }
}
sudo ln -s /etc/nginx/sites-available/authelia-portal /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/panel-protegido /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Configuración de TOTP

TOTP (Time-based One-Time Password) es el método 2FA más común, compatible con Google Authenticator, Authy y cualquier app compatible con RFC 6238.

Registro del dispositivo TOTP

  1. Accede a la aplicación protegida
  2. Authelia te redirigirá al portal de login
  3. Introduce el usuario y contraseña
  4. El sistema te pedirá registrar un dispositivo 2FA
  5. Escanea el código QR con Google Authenticator, Authy o similar
  6. Verifica con el código de 6 dígitos generado

Configuración en Authelia

# En configuration.yml
totp:
  issuer: "Mi Empresa"  # Nombre que aparece en la app de autenticación
  algorithm: sha1       # sha1, sha256, sha512
  digits: 6             # 6 u 8 dígitos
  period: 30            # Segundos de validez de cada código
  skew: 1               # Códigos anteriores/posteriores aceptados (tolerancia de reloj)
  secret_size: 32       # Tamaño del secreto compartido en bytes

Configuración de WebAuthn

WebAuthn permite autenticación con llaves de seguridad físicas (YubiKey) o biometría del dispositivo (Touch ID, Windows Hello).

# En configuration.yml
webauthn:
  disable: false
  display_name: "Mi Dominio"
  attestation_conveyance_preference: indirect  # none, indirect, direct, enterprise
  user_verification: preferred                 # required, preferred, discouraged
  timeout: 60s

Registro de un dispositivo WebAuthn

  1. Tras autenticarte con usuario/contraseña, selecciona "Registrar WebAuthn"
  2. El navegador solicitará la llave de seguridad o biometría
  3. Confirmar el registro siguiendo las instrucciones del dispositivo

Reglas de Control de Acceso

# Ejemplos de reglas avanzadas en configuration.yml
access_control:
  default_policy: deny

  networks:
    - name: red-interna
      networks:
        - 192.168.1.0/24
        - 10.0.0.0/8

  rules:
    # Acceso sin autenticación desde la red interna
    - domain: panel.tudominio.com
      networks:
        - red-interna
      policy: bypass

    # Solo ciertos usuarios pueden acceder al panel de admin
    - domain: admin.tudominio.com
      subject:
        - "group:admins"
      policy: two_factor

    # Rutas específicas con diferente política
    - domain: app.tudominio.com
      resources:
        - "^/api/public.*$"
      policy: bypass

    - domain: app.tudominio.com
      resources:
        - "^/admin.*$"
      subject:
        - "group:admins"
      policy: two_factor

    - domain: app.tudominio.com
      policy: one_factor

    # Todo lo demás requiere 2FA
    - domain: "*.tudominio.com"
      policy: two_factor

Gestión de Usuarios

Archivo de usuarios (para instalaciones pequeñas)

# Generar el hash de la contraseña
docker run authelia/authelia:latest authelia crypto hash generate argon2 --password "contraseña-segura"

# Crear el archivo de usuarios
cat > /opt/authelia/config/users_database.yml << 'EOF'
---
users:
  admin:
    displayname: "Administrador"
    password: "$argon2id$v=19$m=65536,t=3,p=4$SALT$HASH"
    email: [email protected]
    groups:
      - admins
      - users

  jgarcia:
    displayname: "Juan García"
    password: "$argon2id$v=19$m=65536,t=3,p=4$SALT$HASH"
    email: [email protected]
    groups:
      - users
EOF

Integración con LDAP (para organizaciones con directorio)

# En configuration.yml, reemplazar la sección authentication_backend
authentication_backend:
  ldap:
    implementation: custom
    url: ldap://ldap.empresa.com:389
    start_tls: true
    base_dn: dc=empresa,dc=com
    additional_users_dn: ou=usuarios
    users_filter: (&({username_attribute}={input})(objectClass=inetOrgPerson))
    username_attribute: uid
    mail_attribute: mail
    display_name_attribute: cn
    additional_groups_dn: ou=grupos
    groups_filter: (&(member=uid={input},ou=usuarios,dc=empresa,dc=com)(objectClass=groupOfNames))
    group_name_attribute: cn
    user: cn=readonly,dc=empresa,dc=com
    password: clave-readonly-ldap

Solución de Problemas

Authelia muestra "Internal Server Error"

# Ver los logs detallados
docker compose logs authelia --tail 50

# Errores comunes:
# - Secretos demasiado cortos (jwt_secret, session secret necesitan 64+ hex chars)
# - Permisos en /data o /config
docker exec authelia ls -la /config/ /data/

La autenticación en Nginx devuelve 401 constantemente

# Verificar que el snippet está incluido correctamente
sudo nginx -t

# Comprobar que Authelia responde
curl -v http://localhost:9091/api/health

# Ver qué responde Authelia al endpoint de auth
curl -v http://localhost:9091/api/authz/auth-request

Los códigos TOTP no funcionan

# El problema más común es el reloj del servidor desincronizado
# Verificar y sincronizar el reloj
timedatectl status
sudo timedatectl set-ntp true
chronyc tracking  # Si usas chrony

Emails de notificación no llegan

# Para pruebas, usar el notifier de filesystem y revisar el archivo
cat /opt/authelia/data/notifications.txt

Conclusión

Authelia proporciona una solución completa de autenticación de dos factores y control de acceso para toda la infraestructura web, sin depender de servicios externos y con pleno control sobre los datos de autenticación. La combinación de TOTP, WebAuthn y reglas de acceso granulares por dominio, ruta o grupo de usuarios hace de Authelia la opción más flexible para proteger paneles de administración, herramientas internas y cualquier aplicación expuesta a internet.