Authelia: Tu propio proveedor OAuth2 (II) - Añadir un servicio

En esta entrada anterior vimos cómo configurar Authelia como nuestro nuevo proveedor de inicio de sesión SSO o single sign-on. En esta nueva entrada veremos cómo comenzar a usarlo, y qué debemos tener en cuenta a la hora de configurar un servicio para que haga uso de él.

En este tutorial partiremos de la base de que ya tenemos Authelia funcionando, y nos centraremos sólo en la configuración para agregar un nuevo cliente.

En la documentación de Authelia podemos encontrar un sinfín de ejemplos de integraciones con distintos servicios, y para aquellos que no estén listados, podremos basarnos en las documentaciones que nos proveen sobre cómo configurar el acceso OAuth2, con lo que prácticamente tenemos cubierto cualquier caso. Aquí veremos un caso típico que podrá extenderse al resto.

Caso de ejemplo: Portainer

Para este tutorial vamos a configurar el acceso a Portainer, el cual, por si no lo conoces, es una herramienta web open-source que permite gestionar contenedores Docker. Podemos identificar 2 pasos claramente definidos: Configurar el servicio de Portainer y añadir la configuración necesaria a Authelia.

Configuración de Portainer

Lo primero que haremos será acceder a la web de nuestra instancia de Portainer (pongamos para este ejemplo que está alojada en https://portainer.example.org). Una vez dentro, accederemos en el menú de la izquierda a Settings -> Authentication. En la pantalla que nos aparece seleccionaremos la opción OAuth authentication, habilitaremos el selector de Use SSO y como provider marcaremos Custom OAuth provider y dejamos el resto de opciones desmarcadas, como se puede ver en la siguiente imagen:

Selección de proveedor OAuth2 en Portainer

Al seleccionar el proveedor Custom nos aparecerá debajo una serie de campos que deberemos rellenar, y que serán los siguientes:

  • Client ID: Se trata del ID público de nuestra aplicación para OAuth2.
  • Client secret: El secreto que deberemos crear y compartir con Authelia para garantizar el acceso.
  • Authorization URL: URL en la que se encuentra el servicio de Authelia contra el que nos autenticaremos.
  • Access token URL: URL que usará el servicio para intercambiar el código por un token de acceso válido.
  • Resource URL: URL utilizada por el servicio para obtener información del usuario que se va a autenticar.
  • Redirect URL: URL utilizada por Authelia para redirigir al usuario una vez la autenticación se ha completado exitosamente.
  • User identifier: Se trata del identificador que usará Portainer para crear una cuenta para el usuario autenticado. Se obtiene del servidor de recursos especificado a través del campo Resource URL.
  • Scopes: Ámbitos requeridos por Authelia para recuperar información sobre el usuario autenticado.

A modo de ejemplo, nos debería quedar algo similar a esto:

Configuración de ejemplo

En dicha configuración, el client secret vamos a poner, por ejemplo, que sea S^ecreto-1000VecesMásComplicadoQueEsto!. Sólo nos queda guardar los cambios pulsando el botón de Save settings y habremos terminado en este lado.

Configuración en Authelia

Una vez tenemos Portainer configurado, es el turno de ir a por Authelia. Si recordáis en la anterior entrada, teníamos un fichero de configuración llamado configuration.yml en el que dejamos una sección llamada identity_providers que quedó sin explicar. Se trata de la que podemos ver a continuación y que detallaremos en esta entrada:

---
###############################################################
#                   Authelia configuration                    #
###############################################################

# El resto de la configuración de Authelia iría aquí

identity_providers:
  oidc:
    clients:
      - id: portainer
        description: Portainer
        public: false
        secret: ''
        authorization_policy: two_factor
        redirect_uris: https://portainer.example.org
        scopes:
          - openid
          - profile
          - groups
          - email
        consent_mode: implicit
        pre_configured_consent_duration: 1M

...

Configuración a añadir en Authelia bajo identity_providers

Como veis, tenemos creada una entrada bajo clients para Portainer y contiene la siguiente información:

  • id: Debe coincidir con el Client ID que pusimos en Portainer.
  • description: Es una descripción legible por humanos de la aplicación cliente. Esto puede ser útil para la administración y la visualización en las interfaces de usuario. Aquí, la descripción es simplemente Portainer.
  • secret: Es la clave secreta utilizada para autenticar la aplicación cliente con Authelia. Después veremos cómo generarlo
  • public: Este es un booleano que indica si el cliente es público o no. Si es true, el cliente no tiene secreto y no puede mantenerlo. Si es false, es un cliente confidencial que tiene un secreto. En este caso es false, lo que significa que Portainer es un cliente confidencial.
  • authorization_policy: Define la política de autorización requerida para este cliente. En este caso, se ha establecido two_factor, lo que significa que se requiere autenticación de dos factores para autenticarse en este cliente (requerirá una autenticación de contraseña + llave o pin para iniciar la sesión).
  • redirect_uris: Es una lista de URIs a las que Authelia puede redirigir después de la autenticación. En el caso de Portainer bastará con especificar una: https://portainer.example.org.
  • scopes: Son los ámbitos de OIDC que esta aplicación cliente puede solicitar. Los ámbitos determinan qué tipo de información y permisos está solicitando el cliente. En este caso, los ámbitos solicitados son:
    • openid: Es un ámbito requerido para cualquier solicitud de OIDC.
    • profile: Solicita acceso a información básica del perfil del usuario.
    • groups: Solicita información sobre los grupos a los que pertenece el usuario.
    • email: Solicita acceso a la dirección de correo electrónico del usuario.
  • consent_mode: Determina cómo Authelia gestiona el consentimiento del usuario para compartir su información con aplicaciones clientes. En este caso es implicit, que significa que el sistema asumirá automáticamente que el usuario da su consentimiento sin mostrarle explícitamente una pantalla de consentimiento. Es decir, el usuario no necesita dar su aprobación cada vez que una aplicación cliente solicita acceso a su información.
  • pre_configured_consent_duration: Este campo determina durante cuánto tiempo se recuerda el consentimiento dado por el usuario antes de que se le solicite nuevamente. 1M significa que el consentimiento se recuerda durante 1 mes. Después de este período, si el modo de consentimiento lo requiere, se le podría pedir al usuario que dé su consentimiento nuevamente. Esta configuración es útil para no molestar constantemente al usuario con pantallas de consentimiento, pero al mismo tiempo garantizar que se le pregunta periódicamente para volver a confirmar su consentimiento.

Vistos los valores que tenemos que poner en Authelia (básicamente podemos dejar los que hay salvo el redirect_uris que deberá ser el que pusimos en Portainer, nos queda ver cómo generar ese secreto. En el apartado anterior, comentamos que podíamos poner algo como S^ecreto-1000VecesMásComplicadoQueEsto!, pero lo esencial es que éste sea seguro, único y difícil de adivinar. Generalmente, se usa un conjunto de caracteres alfanuméricos aleatorios y, en algunos casos, se incluyen símbolos para aumentar la complejidad. Una forma sencilla de generarlo es utilizando openssl:

openssl rand -base64 32

Generación aleatoria de un secreto con openssl

El resultado del comando habrá que ponerlo tanto en el campo Client secret de Portainer como en el campo secret de Authelia. Sin embargo, podemos ir un paso más y guardar aquí el secreto cifrado, de tal manera que reducimos su exposición ante posibles ataques. Para ello, nos conectamos al contenedor Docker de Authelia mediante docker exec -it authelia sh (o entramos en la máquina donde lo tengamos instalado) y ejecutamos el siguiente comando:

authelia crypto hash generate argon2 --password S^ecreto-1000VecesMásComplicadoQueEsto!

Esto nos generará una salida similar a $argon2id$v=19$m=65536,t=3,p=4$iFl+w0YQgcs4PiooGDuysw$KKhd7TdOjXDfuXezhZOPK4mWYrUlQLLbKFAt4n1F8Ps, y será lo que tengamos que poner en el campo secret de la configuración de Authelia que tenemos más arriba, completando así todos los campos.

Reinicio y prueba

Una vez completadas las configuraciones, deberemos reiniciar el servicio de Authelia y después cerrar la sesión en Portainer. Esto nos llevará a la pantalla de login que ahora se verá así:

Pantalla de inicio de sesión de Portainer con el SSO activado

Si hacemos clic en Login with OAuth veremos cómo nos redirige a Authelia. En caso de que no estemos logados en el servicio deberemos hacerlo (como vimos en la entrada anterior) y acto seguido veremos cómo somos redirigidos a la pantalla principal de Portainer, ya con nuestro usuario y el acceso concedido. Si en la configuración de Authelia el consent_mode fuera explicit o no existiera, la primera vez se nos informará de que Portainer solicita acceso a nuestro perfil, grupos y correo electrónico. Bastará con concederlo y ya.

Para el resto de servicios apenas hay diferencias respecto a este ejemplo con Portainer. Por lo general, donde más atención deberemos prestar es a las URL de redirección o callback, pues sí suelen variar en algunos casos.

También os recomiendo mantener activa la opción de usar la autenticación clásica por usuario y contraseña, de manera que si un día el servicio de Authelia no lo tenemos disponible, ¡no nos quedemos sin poder acceder a nuestros servicios!

Y hasta aquí la segunda parte. Os animo a que integréis el acceso de vuestros servicios con una solución SSO, ya que facilita la gestión de accesos, la hace un poco más segura y, por qué no, más cómoda cuando trabajamos desde un ordenador (o móvil) que nos guarda la sesión de SSO iniciada.

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: