Authelia: Tu propio proveedor OAuth2
Seguro que, en algún momento, todos hemos hecho uso de este tipo de servicios OAuth2, como por ejemplo a la hora de registrarnos en alguna página a través de algún botón tipo "Regístrate con tu cuenta de Google" o "Inicia sesión con tu cuenta de Facebook". Incluso mediante aplicaciones como Gitea, como comentaba en una entrada anterior.
Hoy vengo a hablaros de Authelia. Como dice en su página web, se puede describir como: Un servidor y portal de autenticación y autorización de código abierto que cumple la función de gestión de identidad y acceso (IAM) de la seguridad de la información, al proporcionar autenticación multifactor e inicio de sesión único (SSO) para sus aplicaciones a través de un portal web.
Este servicio me está permitiendo enlazar todas las cuentas que tengo en mi ya extensa nube personal, facilitando el inicio de sesión en ellas y gestionando de manera más efectiva el acceso. Actualmente, lo tengo implementado en algunos de mis servicios y poco a poco lo voy haciendo extensible a todos aquellos que lo soportan de alguna u otra forma.
He comenzado por implementarlo en aquellos servicios que están expuestos al exterior y hago uso de los túneles de Cloudflare para tener una capa extra de seguridad, pues tan sólo se puede acceder a mi instancia de SSO bajo determinadas circunstancias.
Instalación
Comenzaremos viendo, como ya es habitual, el fichero de Docker Compose que usaremos para levantar nuestra instancia. Éste tendrá una forma similar a la siguiente:
Como se puede ver, es bastante sencillo. En este caso lo he puesto con las etiquetas para Traefik, ya que internamente hago uso de dicho servicio para acceder en mi intranet. Además, se conecta a la red que comparte con un servicio de Redis, el cual permite que, cuando reiniciemos Authelia, se mantengan las sesiones abiertas (de lo contrario, con cada reinicio cerraríamos las sesiones y tendríamos que volver a iniciar sesión en Authelia para mantener nuestros servicios con las sesiones activas).
En cuanto al fichero .env
, lo he usado para definir algunas variables de entorno que serán pasadas al campo environment
y tiene esta forma:
Lo he hecho así porque, de esta forma, me es más sencillo hacer una copia en Pass y poder desplegarlo en otro servidor rápidamente, de ser necesario (recordad mantener ese fichero con permisos 0600 para mayor seguridad).
Veamos esos secretos detenidamente:
AUTH_SMTP_PASSWORD
: Este secreto contiene el apikey de mi servidor de correo SMTP, el cual uso para enviar correos electrónicos desde distintos servicios (en este caso, para validar los token de seguridad que uso en Authelia).DB_PASSWORD
: Contiene la contraseña de la base de datos donde Authelia persiste la información.JWT_SECRET
: Define el secreto utilizado para crear tokens JWT aprovechados por el proceso de verificación de identidad.SESSION_SECRET
: La clave secreta utilizada para cifrar los datos de la sesión en Redis.STORAGE_ENCRYPTION_KEY
: Se trata de la clave de encriptación para la información a persistir en base de datos.OIDC_HMAC_SECRET
: Se usa para firmar los token JWT.
Tanto JWT_SECRET
, como SESSION_SECRET
, STORAGE_ENCRYPTION_KEY
o OIDC_HMAC_SECRET
son cadenas de caracteres que deben tener una longitud recomendada mínima de 64 caracteres. Para obtener algo así, basta con ejecutar el comando openssl rand -hex 64
, cuya salida nos dará algo parecido a:
Por último, crearemos la carpeta config
y, dentro de ella, las subcarpetas assets
, keys
y los ficheros users.yml
y configuration.yml
, cuyo contenido veremos en el apartado siguiente. Por ahora, nos quedaremos con que, dentro de assets
, podemos meter nuestro logo (para que en la web aparezca) si añadimos los ficheros favicon.ico
y logo.png
con el icono y logo que queramos usar.
Configuración
Una vez generado todo lo que necesitamos para la instalación, pasaremos a la configuración del servicio de Authelia propiamente dicho, el cual se basa en ficheros YML (no dispone de interfaz gráfica).
Usuarios
Para configurar los usuarios, editaremos el fichero users.yml
que creamos previamente en la carpeta config
. La función de dicho fichero será definir los usuarios con los cuales podremos iniciar sesión en Authelia y, por lo tanto, en las aplicaciones que la usen como SSO. Si bien se puede enlazar con un LDAP, para este tutorial lo haremos por fichero, pues es más sencillo, y dejaremos ese caso para otra entrada. Su contenido será algo similar a esto:
El fichero se explica por sí solo: Anidado en users
tendremos el nombre de usuario que queremos dar de alta (podemos agregar tantos como queramos, respetando el formato YML) y, dentro de éste, podremos habilitarlo o deshabilitarlo, especificar el nombre que se mostrará en la web, su contraseña, correo electrónico (para recibir los correos de Authelia que nos permiten validar token) y los grupos a los que pertenece el usuario, que en este caso serán admins
y dev
. Estos grupos deberán estar asociados al usuario administrador de la instancia.
Respecto a la contraseña, lo ideal es poner un hash de la misma, en lugar de en texto plano directamente. Authelia viene con un generador de encriptación, que podemos usar de la siguiente forma:
Mediante dicho comando, correremos la imagen de Authelia para que nos genere un hash de la contraseña MiSuperPassword, el cual será el que pegaremos en el campo password
de nuestro usuario pepito
.
Configuración de las claves
Estas claves son necesarias para que Authelia opere como proveedor OpenID Connect. En este caso, serán 2 claves RSA que estarán bajo el nombre de public.pem
y private.pem
, haciendo referencia a las claves pública y privada, respectivamente.
Configuración de Authelia
Una vez tenemos el o los usuarios "registrados", pasamos a editar el contenido dle fichero configuration.yml
, el cual pasará a tener el siguiente formato:
Es un poco largo, así que lo analizaremos por secciones:
La variable default_redirection_url
contendrá la URL donde queremos exponer nuestro servicio de Authelia, mientras que default_2fa_method
le indica cuál será el sistema de autenticación por defecto (webauthn para usar token de seguridad como los de Yubikey, o totp para que, por defecto, se nos pida un código generado por aplicaciones como Aegis o Google Authenticator).
Mediante la variable theme
, podemos definir el tema de la web app, ésta puede ser light
, dark
o grey
, que, para mi gusto, es un tema oscuro más bonito que el dark
.
Bajo server
, definimos los host desde los que se puede acceder a Authelia. Al estar en un contenedor Docker, lo suyo es especificar que cualquiera puede alcanzarlo, mediante la IP 0.0.0.0
. El puerto expuesto será el 9091 y la ruta para los assets
(el logo y el favicon) se encuentra en este caso bajo /config/assets
.
Podemos definir el nivel de log a través de log.level
.
Bajo totp.issuer
especificamos el texto que queremos que aparezca cuando damos de alta el servicio en una aplicación 2FA, yo aquí prefiero poner el host y así veo, de un plumazo, qué servidor estoy usando.
Con authentication_backend
especificamos dónde se encuentran los usuarios autorizados. Como comentaba anteriormente, se puede conectar Authelia a un servidor LDAP, pero para este tutorial los hemos registrado mediante el fichero users.yml
, lo cual indicamos mediante el identificador file.path
y la ruta al mismo. En caso de usar este sistema, los usuarios no podrán resetear sus contraseñas, con lo que seremos los encargados de mantenerlas.
Mediante access_control
podemos definir reglas que nos permiten simplificar el inicio de sesión bajo determinadas condiciones. En este caso, hemos definido la política por defecto default_policy
a deny
, de manera que, de base, denegamos el inicio de sesión, y sólo lo autorizamos para los casos en los que los servicios vengan de cualquier subdominio de example.org
. Además, si accedemos desde una IP concreta o una subred (en este caso una VPN), no solicitaremos ningún tipo de autenticación, mientras que si no es así, pediremos tanto el usuario y contraseña, como un 2FA. Esto es útil para casos como el que tengo en casa, donde en mi LAN no necesito andar registrándome pero si me conecto por una VPN sí quiero forzar que eso ocurra (ya que no tengo expuesto el acceso desde el exterior, con lo que en mi caso particular las reglas son un poco distintas).
En session
definimos datos de la sesión de Authelia, como el tiempo máximo de vida antes de que caduque o el tiempo de inactivación máxima que tendrá. El name
nos permite darle un nombre a esa cookie
y domain
nos permite separar dicha sesión por dominios. En caso de usar un Redis, especificaremos el host y el puerto en el que se encuentra.
El campo regulation
actúa como un Fail2Ban, de forma que nos permite un máximo número de intentos a la hora de iniciar sesión, el tiempo máximo que nos dará para cada uno, y el tiempo de baneo del origen en caso de superar dichos intentos. Útil para evitar ataques de fuerza bruta.
Con storage
definimos dónde almacenará Authelia la información. Aquí podemos hacer uso de una base de datos PostgreSQL, un MariaDB... o directamente un SQLite. En este último caso, será tan sencillo como indicar el fichero .db
que la contendrá: storage.local.path:/config/db.sqlite3
.
Mediante notifier
podremos indicar la configuración SMTP para que Authelia nos envíe los correos necesarios para dar de alta dispositivos Web-Authn, resetear contraseñas (en los casos que se permita), etc. No voy a entrar en detalle en los campos, ya que son bastante descriptivos, pero sí quiero comentar una cosa: Si no queremos configurar esta parte (bien porque estamos probando, bien porque no lo vamos a necesitar mucho), Authelia nos provee de un sistema de notificación por fichero. Si ponemos la siguiente configuración:
Authelia escribirá en un fichero notification.txt
lo mismo que nos mandaría al correo, con lo que bastaría con acceder a dicho fichero y mostrar su contenido. Un ejemplo de ello sería:
A través de identity_providers.oidc
definiremos los clientes que podrán usar el servicio. Estos clientes los podemos ver listados en https://www.authelia.com/integration/openid-connect/, junto con la configuración que cada uno requiere. Esta lista es extensa, y poco a poco va creciendo, pero cualquier servicio que soporte OAuth2, debería ser posible configurarlo, tomando cualquiera de los ejemplos de esa lista como plantilla. Para este tutorial, podemos borrar por completo esta sección, ya que nos centraremos sólo en el servicio de Authelia en sí.
Accediendo al servicio
Una vez tenemos configurado todo, ya podemos levantar nuestro servicio de Authelia mediante el ya confiable docker compose up -d
y acceder a la URL donde lo hayamos expuesto (según el ejemplo: https://auth.example.org
). Esto nos mostrará una ventana similar a:
En ella, sólo tendremos que iniciar sesión con nuestro usuario y contraseña, definidos en el fichero users.yml
y nos encontraremos con lo siguiente:
Como podéis ver, nuestro usuario Pepito necesita definir un dispositivo 2FA la primera vez que inicia sesión (y más concretamente, una Security Key, ya que indicamos que éste sería el sistema por defecto en la configuración), con lo que procedemos a registrarlo mediante el enlace Registrar Dispositivo. En cuanto hacemos clic, se nos enviará un correo con un enlace al que debemos acceder y que nos permitirá registrar nuestro dispositivo (recordad que, si habéis optado por la opción de file
en lugar de un proveedor de correo, deberéis fijaros en el contenido del fichero config/notification.txt
o el que hayáis puesto en la configuración):
Una vez lo hagamos, veremos que hemos logrado iniciar sesión gracias al check verde:
Con esto, ya tendremos nuestra sesión de Authelia iniciada. Cualquier aplicación que conectemos con ella, si está en este estado, automáticamente nos redirigirá de nuevo a la aplicación, pero ya con nuestro inicio de sesión correcto.
Al final ha quedado un poco extenso el tutorial, pero nos vale para tener nuestro propio proveedor de OAuth2 listo para usar en nuestras aplicaciones. En futuras entradas veremos cómo configurarlo con un servidor LDAP para gestionar de manera más sencilla los usuarios y grupos y algún ejemplo de integración.
Si te ha gustado la entrada, o te ha sido útil y quieres ayudarme a pagar los gastos que conlleva el servidor y mantener así el blog libre completamente de anuncios, puedes hacer una donación en Bitcoin en la siguiente dirección: