Intégrer Alfresco à un système d’authentification unique (SSO) a toujours été un sujet complexe à aborder. C’est un sujet qui revient à chaque nouveau déploiement d’Alfresco chez nos clients et il n’y a pas de réponse toute prête à apporter :

Le but est d’arriver à faire correspondre les attentes du client en terme d’authentification (prendre en compte l’existant et la cible à atteindre), les possibilités offertes par Alfresco et les contraintes techniques. Et tout ceci en conservant un bon niveau de sécurité.

Dans ce billet, nous allons aborder le mécanisme de SSO « External authentication » proposé par Alfresco. C’est le plus simple à comprendre et il est facile à mettre en place. C’est également l’occasion de donner une suite à un billet de blog écrit il y a plus de 10 ans sur le même sujet. À l’époque le sujet concernait la mise en place d’un SSO entre Alfresco Explorer et Share via l’utilisation de CAS. Nous allons voir que l’intégration de CAS est maintenant grandement facilitée.

Cette introduction étant déjà bien trop longue, commençons tout de suite avec une rapide présentation du « External authentication ».

# Principe de fonctionnement

Ce billet n’a pas pour but de remplacer la documentation officielle, je vous invite donc à la lire en complément de ce billet. Toutefois, ne vous laissez pas influencer par la documentation, celle-ci fait souvent référence à CAS mais le système « External authentication » n’est pas lié à un mécanisme de SSO particulier. Et c’est d’ailleurs là tout son intérêt et sa simplicité :

  • l’authentification (unique ou pas d’ailleurs) est déportée en amont d’Alfresco (d’où le « External », ce n’est plus Alfresco qui gère l’authentification, mais un élément externe)
  • l’information sur l’utilisateur authentifié est portée par un en-tête HTTP
  • Alfresco et Share utilisent le contenu de cet en-tête pour authentifier automatiquement l’utilisateur (une confiance totale est faite au contenu de cet en-tête)

 

Schéma du principe de fonctionnement

 

Le mécanisme « External authentication » ne présuppose en aucun cas de la méthode utilisée pour authentifier l’utilisateur. Le seul pré-requis concerne la présence de l’en-tête HTTP contenant le login de l’utilisateur. Le nom de cet en-tête est configurable côté Alfresco, vous pouvez utilisez n’importe quelle valeur (dans la suite de ce billet, nous utiliserons X-Alfresco-Remote-User). La valeur de l’en-tête doit contenir uniquement le login de l’utilisateur, tel que connu par Alfresco. Les comptes étant créés généralement via une synchronisation avec un annuaire LDAP, il faut bien s’assurer que le contenu de l’en-tête correspond au login remonté par la synchronisation LDAP.

Et c’est tout ce qu’il faut savoir sur cette méthode d’authentification.

Point important à noter : il s’agit d’un mécanisme d’authentification qui fonctionne uniquement en HTTP. N’espérez pas le faire fonctionner avec d’autres protocoles comme CIFS ou FTP.

# Proxy authentifiant ?

Vous avez certainement remarqué la présence du proxy authentifiant sur le schéma juste au-dessus. Il s’agit de la brique réalisant l’authentification des utilisateurs. Le mécanisme utilisé pour authentifier les utilisateurs n’a aucune incidence sur la partie Alfresco ou Share, du moment que l’en-tête est bien présent avec la bonne valeur. Et vous êtes libre d’utiliser ce que vous voulez à ce niveau.

Concrètement, tous les modules d’authentification gérés par Apache HTTPD sont possibles : CAS bien sûr, mais également SAML, Kerberos ou OpenID Connect. On peut même envisager de l’authentification à deux facteurs (plus connu sous le nom 2FA) et de l’authentification via certificat.

Si vous préférez Nginx, ne partez pas, il y a tout ce qu’il faut (ou presque) : CAS, OpenID Connect, Kerberos, certificat , etc.

Il est également possible d’utiliser des solutions plus complètes du type LemonLDAP::NG. Configuré en tant que reverse-proxy authentifiant devant les applications Alfresco et Share, vous aurez alors accès à un nombre impressionnant de backends pour réaliser l’authentification.

Bref, le choix ne manque pas et vous trouverez certainement votre bonheur avec tous ces modules d’authentification.

# Configuration d’Alfresco

Côté serveur Alfresco, il y a 3 éléments à configurer :

  • Tomcat
  • Alfresco lui-même
  • Share

Ces trois points de configuration seront toujours les mêmes quelque soit le mécanisme utilisé au niveau du proxy authentifiant. À noter que les exemples de configuration concernent Alfresco 6.2. Il faudra les adapter pour les autres versions d’Alfresco.

# Tomcat

Il faut indiquer à Tomcat de propager l’authentification provenant du proxy authentifiant vers les applications. Ceci est valable uniquement si vous utilisez le connecteur AJP entre le proxy authentifiant et Tomcat. Si vous passez par le connecteur HTTP ou HTTPS, cette étape n’est pas nécessaire.

  • dans le fichier conf/server.xml
  • ajouter l’attribut tomcatAuthentication=false au connecteur AJP :

# Alfresco

Il faut ajouter un nouveau type d’authentification (de type external) dans votre chaîne d’authentification.

  • dans le fichier shared/classes/alfresco-global.properties
  • modifier le paramètre authentication.chain pour lui ajouter une authentification de type external
  • ajouter également les paramètres suivants pour configurer l’authentification external

Vous l’aurez compris, le paramètre external.authentication.proxyHeader doit correspondre au nom de l’en-tête envoyé par le proxy authentifiant.

# Share

La configuration de Share passe par la création de fichiers XML à placer dans le dossier shared/classes/alfresco/web-extension/.

  • créer le fichier external-auth-context.xml avec le contenu suivant :
  • créer le fichier external-auth-config.xml avec le contenu suivant :

N’oubliez pas de modifier la balise userHeader avec la nom de l’en-tête envoyé par le proxy authentifiant.

# Comment tester ?

Rien de plus simple, une simple commande curl en vous assurant de passer l’en-tête attendu par Alfresco :

  • accès à la console d’administration d’Alfresco

Alfresco répond avec un code 200 OK, tout va bien, on a été authentifié et l’accès à la console d’administration est autorisé. Un code 401 Unauthorized aurait indiqué un échec d’authentification et donc un souci dans la configuration d’Alfresco.

  • accès au Tableau de bord de Share

L’authentification a également fonctionné avec Share : nous obtenons une redirection 302 Found vers le tableau de bord de l’utilisateur admin (voir l’en-tête HTTP Location dans la réponse). En cas d’échec d’authentification, la redirection aurait été faite vers le formulaire d’authentification Location: /share/page?pt=login).

# Et  niveau sécurité ?

Bonne remarque ! Comme souvent avec les composants qui touchent à la sécurité et à l’authentification, il ne faut pas juste s’arrêter à « Ça fonctionne, je ne touche plus à rien ». Il est important de bien comprendre ce que nous venons de faire.

Comme vous l’avez certainement compris, Alfresco fait totalement confiance à la valeur de l’en-tête pour authentifier l’utilisateur. Il faut donc faire en sorte que l’en-tête arrivant au niveau d’Alfresco soit digne de confiance. Il est très facile pour un attaquant de forger un en-tête malveillant et ainsi se faire passer pour n’importe quel autre utilisateur. Il n’est pas nécessaire de connaitre toutes les options de la commande curl pour y arriver, il existe des extensions pour nos navigateurs préférés dont le but est de créer et/ou modifier les en-têtes HTTP (par exemple Modify Header Value pour Firefox).

Les bonnes pratiques à respecter :

  • autoriser l’accès à Alfresco/Share uniquement depuis le proxy authentifiant
  • le proxy authentifiant doit supprimer les en-têtes X-Alfresco-Remote-User des requêtes entrantes

Pour le premier point, il est possible de mettre en place des règles de filtrage du trafic entrant avec l’utilisation d’un firewall directement sur le serveur Alfresco, ou via le Remote Address Filter de Tomcat. Uniquement le proxy authentifiant doit être autorisé à accéder à Tomcat. Cependant, ceci ne vous protégera pas des attaques locales (si l’attaquant à accès au serveur, il shunte toutes ces protections).

Pour le second point, cela dépend du proxy authentifiant utilisé. Par exemple avec Apache HTTPD, il est possible de supprimer l’en-tête des requêtes entrantes avec la directive RequestHeader suivante :

Pour aller plus loin, il est également possible de mettre en place un mécanisme d’authentification mutuelle en TLS entre le proxy authentifiant et Tomcat. Le proxy authentifiant se connecte en TLS et présente un certificat client à Tomcat, celui-ci est configuré pour valider le certificat présenté. Alfresco va ensuite vérifier que ce certificat correspond à l’utilisateur indiqué par le paramètre external.authentication.proxyUserName (ce même paramètre que nous avions laissé vide dans l’exemple de configuration d’Alfresco ci-dessus). Si tout est ok, la requête continue son chemin et Alfresco utilise toujours l’en-tête HTTP pour authentifier l’utilisateur.

L’utilisation d’un certificat client permet une authentification mutuelle entre le proxy authentifiant et Tomcat. Il est ainsi possible d’établir une relation de confiance entre ces deux applications et de garantir l’authenticité de l’en-tête HTTP. Sans le certificat client, pas d’accès possible à Tomcat.

Si mon explication est suffisamment claire, et si vous connaissez un peu Alfresco, vous aurez remarqué qu’il s’agit du même principe déjà utilisé entre Alfresco et Solr (même si la mise en œuvre est différente, le principe reste identique).

# Mon Webdav ne fonctionne plus !

Depuis le début de l’article, je pars du principe que nous souhaitons authentifier un utilisateur dans un contexte purement web (en HTTP) et souhaitant accéder à l’interface Share. Cependant Alfresco propose bien plus de services que l’interface Share : Webdav, différentes API (REST, CMIS), l’édition en ligne avec MS Office (AOS), etc. Ces différents services reposent généralement sur leur propre mécanisme d’authentification, et il est rare que le mécanisme d’authentification mis en place au niveau du proxy authentifiant soit utilisable directement.

Comme exemple parlant, prenons le cas de l’accès au partage Webdav d’Alfresco avec une authentification CAS au niveau du proxy authentifiant. À ma connaissance, aucun client Webdav ne sait gérer l’authentification CAS. Sans action particulière, il ne sera plus possible d’utiliser l’accès Webdav via le proxy authentifiant.

Autre exemple : Share offre la possibilité de créer un lien public vers un document. Toutes les personnes connaissant ce lien peuvent avoir accès au document sans authentification ni compte dans Alfresco … sauf que le proxy authentifiant va jouer son rôle et va imposer une authentification, même pour accéder à une ressource considérée comme publique au niveau de Share.

Pour retrouver le comportement standard d’Alfresco et de Share il sera nécessaire de configurer le proxy authentifiant pour ajouter des exceptions. Le but est de laisser passer certaines URL sans nécessité d’avoir un utilisateur authentifié. Cette configuration étant réalisée au niveau du proxy authentifiant, on déborde du périmètre de billet et sa mise en place est laissé comme exercice au lecteur (ce billet étant déjà bien trop long).