Retour : page principale > sommaire applications générales > application annuaire

Documentation SSO (service:annuaire:auth)

Le SSO ou Single Sign On est implémenté à l'aide d'une authentification à base de jetons JWT signés mais non chiffrés (shaken, not stirred), depuis la version 1.4 de l'annuaire.
Pour l'instant il n'implémente pas OAuth ni OpenIDConnect.
Note : prononcer "cine gueule saille nonne" et non "saingle si nyon", et encore moins "sein gueule sa nyonne" ou toute autre approximation foireuse.

Notes sur l'intégration : MemoIntegrationSSO
Tester ses jetons JWT : https://jwt.io/

Installations

URL racine des services (une auto-documentation est proposée à ces adresses) :

Widgets de [dé]connexion :

Liste des webservices


connexion

Vérifie l'identité d'un utilisateur à partir de son courriel et son mot de passe ou d'un cookie; lui accorde un jeton et un cookie si tout va bien, sinon renvoie une erreur et détruit le cookie.
Attention, si vous n'utilisez pas urlencode() pour fournir le mot de passe, le caractère "&" posera problème en GET (POST n'est pas supporté pour l'instant)

On peut se connecter à l'aide d'un fournisseur d'authentification partenaire (ex: Pl@ntNet), en spécifiant le paramètre "partner", qui n'accepte qu'une liste restreinte de valeurs non divulguée par l'API (ex: "plantnet").

Retour en cas de succès :
  • session : true
  • token : le jeton JWT encodĂ© en base 64
  • duration : durĂ©e de validitĂ© du jeton en secondes
  • token_id : l'identifiant du jeton aussi utilisĂ© comme nom de cookie
  • last_modif : timestamp unix de la dernière modification du profil utilisateur dans l'annuaire (pour les partenaires dĂ©sirant synchroniser des donnĂ©es)


Exemples :

Alias :
  • connexion
  • login

deconnexion

Détruit le cookie et renvoie un jeton NULL. C'est au client d'annuler son jeton stocké précédemment. De façon générale le client devrait toujours remplacer son jeton par celui renvoyé par les méthodes de l'annuaire.

Retour en cas de succès :
  • session : false
  • token : null
  • token_id : l'identifiant du jeton aussi utilisĂ© comme nom de cookie

Exemple :

Alias :
  • deconnexion
  • logout

identite

Renvoie un jeton rafraîchi si l'utilisateur est reconnu comme détenteur d'une session active (cookie valide, header HTTP "Authorization" ou jeton valide); renvoie une erreur si le cookie et/ou le jeton sont expirés.
Cela permet en théorie de forger des cookies avec des jetons expirés pour se les faire rafraîchir frauduleusement, mais le canal HTTPS fait qu'un client ne peut être en possession que de ses propres jetons... au pire on peut se faire prolonger à l'infini même si on n'est plus inscrit à l'annuaire...
Note : pour conserver cette confidentialité, toute application qui reçoit un jeton doit s'arranger pour ne pas le transmettre en clair à qui que ce soit d'autre
Priorité : cookie > header "Authorization" > paramètre "token"

Retour en cas de succès :
  • session : true
  • token : un nouveau jeton JWT encodĂ© en base 64, "rafraĂ®chi" : mĂŞmes donnĂ©es que le jeton fourni (ou correspondant Ă  l'utilisateur dĂ©tenteur du cookie fourni), avec une durĂ©e de vie renouvelĂ©e
  • duration : durĂ©e de validitĂ© du jeton en secondes
  • token_id : l'identifiant du jeton aussi utilisĂ© comme nom de cookie

Exemples :

Alias :
  • identite
  • identity
  • rafraichir
  • refresh

verifierjeton

Vérifie si un jeton est valide; retourne true si oui, une erreur avec des détails si non.
Toute application possédant un jeton qu'elle n'a pas reçu directement de l'annuaire devrait le faire valider auprès de ce service avant de le considérer comme authentique.
Priorité : header "Authorization" > paramètre "token"

Retour en cas de succès :
  • true

Exemples :

Alias :
  • verifierjeton
  • verifytoken

Utilitaires (scripts)

Forger un jeton administrateur longue durée

Par défaut les jetons expirent au bout de 15 minutes.
Une application ayant besoin d'accéder aux services d'une autre en tant qu'administrateur (ex: le site Web a besoin d'agir sur le gestionnaire de listes de discussion) doit stocker un jeton administrateur longue durée.

Un tel jeton se forge Ă  l'aide du script admin :
php scripts/admin.php forger_jeton_admin

Il est associé à l'adresse fictive sso-admin@tela-botanica.org et est valable jusqu'en 2050.
Il ne faut bien sûr jamais le divulguer ni permettre à qui que ce soit d'y accéder.

En cas de compromission d'un jeton

Si un jeton avec pouvoir se promène dans la nature, a été volé ou divulgué par erreur, il faut changer la clef de l'annuaire (config/clef-auth.ini)
Cela provoquera une erreur de signature sur tous les jetons existants, qui seront alors inefficaces.

Structure et décodage d'un jeton

RTFM, ou sinon :
Un jeton est composé de trois parties séparées par des . et encodées chacune en base64.
entete.corps.signature
La signature est un hachis du corps, de l'entête et d'une clef secrète possédée par l'émetteur seulement : elle garantit que le contenu du jeton n'a pas été altéré.

Attention pour décoder ces jetons, il faut utiliser la méthode urlSafe base64 sans quoi ça peut rater dépendamment de ce qu'il y a dans le jeton (URL de l'avatar, notamment) : atob() en Javascript le fait tout seul, mais pas base64_decode() en PHP, par exemple.
En PHP, utiliser la lib JWT (utilisée par l'annuaire pour encoder les jetons) ou une méthode telle que celle-ci :
/**
     * Decode a string with URL-safe Base64.
     *
     * @param string $input A Base64 encoded string
     *
     * @return string A decoded string
     */
    public static function urlsafeB64Decode($input)
    {
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $padlen = 4 - $remainder;
            $input .= str_repeat('=', $padlen);
        }
        return base64_decode(strtr($input, '-_', '+/'));
    }


Contenu d'un jeton

Pour les curieux, utiliser par exemple http://jwt.io/ pour décoder un jeton - ATTENTION la possibilité de le décoder n'implique pas qu'il soit authentique ni valide.

{
  "iss": "https://www.tela-botanica.org", (fournisseur)
  "token_id": "tb_auth_beta_preprod", (identifiant du jeton, qui est aussi l'identifiant du cookie HTTPS posé lors de la réception d'un jeton)
  "sub": "test@megatest.fr", (utilisateur)
  "iat": 1485858115, (date de création)
  "exp": 1485870517, (date d'expiration)
  "scopes": [ (requis par le standard, pourrait peut-être être utilisé à la place de "groupes" ?)
    "tela-botanica.org"
  ],
  "id": "1234567", (id numérique de l'utilisateur, usage interne)
  "prenom": "Micheline",
  "nom": "Plantenette de la Motte",
  "pseudo": "micheline plantenette",
  "pseudoUtilise": true, (si true, l'intitulé sera le pseudo, sinon l'intitulé sera "prénom nom")
  "intitule": "micheline plantenette", (identité publique de l'utilisateur à afficher)
  "avatar": "//www.gravatar.com/avatar/b0288e3532769072f1b51e68b7310702?s=50&r=g&d=mm",
  "groupes": { (identifiant des groupes et rôle dans chaque groupe, définis par le backend de l'annuaire TB - actuellement Wordpress)
    "1": "adm"
  },
  "permissions": [ (noms des rôles, définis par le backend de l'annuaire TB - actuellement Wordpress)
    "administrator"
  ],
  "partenaire": "plantnet", (uniquement dans le cas d'une connexion Ă  travers un partenaire)
  "jetonPartenaire": "eyJ0eXAiOiJKV(...)", (jeton d'origine émis par le partenaire, le cas échéant - attention à la longueur totale du jeton !)
  "nomWiki": "MichelinePlantnette", (nom en CamelCase utilisé dans les Wiki de TB, construit à partir du pseudo ou des nom/prénom)
  "dateDerniereModif": 1476707671 (dernière modification du profil, utile pour la synchronisation de comptes partenaires)
}