Authentification CAS

De WikiBR

Sigma permet à des sites externes (binets en particulier) d'utiliser sa base de données pour authentifier les utilisateurs à travers le protocole CAS 3.0.

Le serveur CAS est situé à l'adresse cas.binets.fr et est lié à la base de données Sigma. Si vous souhaitez que l'ensemble du personnel de l'École (élèves compris) puisse s'authentifier, vous pouvez utiliser le metacas.binets.fr qui est lui lié au LDAP de l'École.

Le webmaster du site en question doit auparavant faire une demande de mise en place de ce système en créant une tâche PaniX. Il doit alors donner :

  • l'url complète de la page de login de son site (plus précisément, l'URL de callback)
  • les informations auxquelles il souhaite accéder
  • son choix entre cas et metacas
  • une justification de la demande

Si la demande est acceptée, un membre du BR va alors inscrire son site dans notre base de données de sites externes.

Le domain `localhost` fait également partie des domaines acceptés par le cas. Cela permet de faire des tests en développement et de faire fonctionner le site à l'identique.

Liste des informations disponibles

Tu peux demander l'accès aux informations

  • noms : prénom, nom, surnom, identifiant BR
  • adresse mail
  • téléphone
  • photo : URL vers la photo TOL
  • numéro de chambre
  • date de naissance
  • groupes : promo, section, binets …
  • droits : droits dans les groupes associés (membre, speaker, admin, follower)
  • nationalité

Attention, le nom des attributs varie entre le domaine localhost et les autres domaines (pour une raison inconnue). Par exemple, en production, on trouve `prenom` et `nom` alors que pour localhost on trouve `givenName` et `sn`.

Pour les développeurs

CAS de développement

Pour le développement, il est possible d'utiliser un serveur CAS de test qui tourne dans un container Docker avec des données fictives, ce qui permet de tester facilement les différents privilèges et le fonctionnement de la connexion. Le projet est disponible sur GitLab.

En PHP

Le plus simple en PHP est d'utiliser la librairie phpCAS.

Code de la page d'identification en PHP

Ci-dessous un exemple très simple et commenté de script d'authentification, à mettre sur votre site :

<?php
include 'CAS_auth.php';
if(!isset($_GET['ticket'])){
  CAS_do_auth();
}
$auth = CAS_get_response();

// et voila !
// les données sont stockées dans $auth = array(key, value, ...);

(ne pas oublier d'enregistrer ces infos dans la Session après ...)

Code des fonctions utilisées dans CAS_auth.php

<?php

function CAS_do_auth(){
  /**
   * url de la page de login, doit correspondre *exactement* à celle donnée lors de l'inscription
   */
  $site = 'http://monsite/login';
  /**
   * Il est possible de forcer la reconnexion et d'ignorer ainsi une connexion passée.
   */
  $reconnexion = false;
   header('Location: https://cas.binets.fr/login?service='.rawurlencode($site).'&renew='
.$reconnexion);
}

function CAS_get_response(){
   $site = 'http://monsite/login';

  /**
   * Récupération de l'id de l'utilisateur correspondant à ce ticket, ainsi que les informations demandées
   */
  $response = file_get_contents('https://cas.binets.fr/serviceValidate?service='.rawurlencode($site ).'&ticket='
.$_GET['ticket']);

  $doc = new DOMDocument();
  $doc->loadXML($response);

  if ($doc->getElementsByTagName('authenticationFailure')->length == 0) {
    $return = array();
    /**
     * Récupération de l'id de l'utilisateur
     */
    $return['id'] = $doc->getElementsByTagName('user')->item(0)->textContent;
    /**
     * Récupération des données de l'utilisateur
     */
    foreach ($doc->getElementsByTagName('attribute') as $attribute) {
      if (isset($return[$attribute->getAttribute('name')])) {
        if (!is_array($return[$attribute->getAttribute('name')])) {
          $return[$attribute->getAttribute('name')] = [$return[$attribute->getAttribute('name')]];
        }
        $return[$attribute->getAttribute('name')][] = $attribute->getAttribute('value');
      } else {
        $return[$attribute->getAttribute('name')] = $attribute->getAttribute('value');
      }
    }
    return $return;
  } else {
    return false;
  }
}

Bugs vécus

Si l'authentification ne fonctionne pas sur certains navigateurs, vérifier les variables $_GET car elles sont peut être doublement encodées. Dans ce cas, soit refaire urldecode, soit un $s = str_replace('%22','"',$s); Si il y a un problème avec les encodages en \u{whatever} pour les caractères accentués, voila une fonction qui peut vous servir (reconversion en UTF-8) :

function jsonClean($s) {
   return preg_replace("/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))",$s);
}

Avec NodeJS

On utilise le paquet cas-authentication.

La page descriptive du package décrit bien comment utiliser le middleware.

Notes

  • Pour récupérer les attributs, préciser session_info dans la configuration de cas-authentification
  • Pour un exemple basique, voir ici

Avec Django

  • Installer le paquet django_cas_ng : pip install django-cas-ng
  • Ajouter ce paquet à la liste des applications :
INSTALLED_APPS = [
    ...
    'django_cas_ng',
    ...
]
  • Configurer la connexion au serveur CAS du BR :
AUTHENTICATION_BACKENDS = (
  'django.contrib.auth.backends.ModelBackend',
  'django_cas_ng.backends.CASBackend',
)
CAS_SERVER_URL = "https://cas.binets.fr/"
  • Renseigner les pages de connexion (dans my_project/urls.py par exemple):
from django_cas_ng.views import login, logout

urlpatterns = [
    ...
    url(r'^login$', login, name='cas_ng_login'),
    url(r'^logout$', logout, name='cas_ng_logout'),
    ...
]
  • Ajouter l'URL d'entrée : LOGIN_URL = "login"

Attention à forcer l'authentification pour les pages concernées :

from django.contrib.auth.decorators import login_required

@login_required
def my_awesome_view(request):
    ...

À noter :

  • le nom de l'utilisateur connecté se trouve dans : request.user.username (accessible dans n'importe quelle vue).
  • les attributs du ldap peuvent être disponibles (demander les attributs nécessaires lors de la mise en place du CAS). Ils sont alors disponibles dans request.session['attributes'].
  • plus d'options de configuration sont présentées [ici]

Avec Flask

On utilise le module [flask-cas]. Voir un exemple [ici].

Avec Drupal

L'implémentation de l'authentification avec un CMS comme Drupal n'est pas forcément évidente. Si vous avez une question, vous pouvez contacter Antoine Sauvage