Comprendre la sécurité de LTI 1.3
Comment retrouver les membres inscrits a un cours ou à une activité ?
Framework de sécurité
LTI1.3 est fondé sur le standard openId Connect. Il est essentiel de bien comprendre cette spécification car de nombreux éléments du vocabulaire LTI est en fait issu d’OpenId connect. Il s’agit d’une couche de sécurité construite au dessus du standard oAuth2 et développée par la fondation openId et la spécification se trouve ici. Je vous propose dans ce post de découvrir et approfondir cette spécification qui est un prérequis pour comprendre LTI. Ce post a pour vocation d’éclaircir les bases nécessaire pour tous le dossier LTI pas seulement LTI1.3 mais également comprendre les services (AGS, NPRS, DL etc…). 1EdTech utilise des mécanismes avancés d’OpenId Connect que l’on va démystifier ici.
Openid connect
OpenID Connect est un standard d’identité qui s’appuie sur OAuth 2.0 pour fournir une couche d’authentification. Il permet aux utilisateurs de se connecter à des applications tierces en utilisant leurs identifiants d’un fournisseur d’identité (IdP) sans avoir à créer de nouveaux comptes, c’est ce que l’on voit fréquement avec Se connecter avec Google par exemple. Cela simplifie l’expérience utilisateur et renforce la sécurité en centralisant l’authentification. C’est précisément ce que cherche LTI, éviter la création de comptes sur un outils tiers.
Les Acteurs
Dans un échange de contenus éducatifs via LTI, il n’y a que deux acteurs, le LMS et l’outils externe. il faudra donc identifier qui sera l_idendity provider_ et qui sera l’application cliente. l’identity provider c’est celui qui connait les utilisateurs c’est donc le LMS alors que l’application cliente,c’est l’outil si le LMS et l’outil sont dans des organisation différente l’application cliente est appelée Third Party Application Client . Les utilisateurs se connectent à l’outil via le LMS ce qui revient à dire : Les utilisateurs se connectent au Third Party Application Client avec L’identity Provider.
Le Json Web Token (JWT)
Pour que l’utilisateur soit connu de l’outil LTI, il faut que le LMS lui envoie les informations de l’utilisateur. OAuth2 permet de déléguer des autorisations d’accès à une ressource. OpenID Connect ajoute au-dessus d’OAuth2 une couche d’identité via l’id_token.. Un token est une preuve numérique infalsifiable qu’un système de confiance a émise. Il est signé cryptographiquement par son émetteur
OopenId Connect comporte deux types de token :
-
L’access token : Issue d’oAuth2 qui caractérise seulement les autorisation mais pas l’identification. C’est la même idée qu’un ticket de cinéma. Quand vous le présentez au contrôleur à l’entrée de la salle, il vérifie que le ticket est valide, que la séance est la bonne et que la date correspond. Il ne sait pas qui vous êtes, il ne vous demande pas votre nom. Le ticket suffit à prouver que vous avez le droit d’entrer.
-
L’id token : C’est la couche d’identité ajouté par OpenId Connect. cette fois c’est la même idée qu’un badge de conférence par exemple. Ce badge porte votre nom, votre prénom, votre organisation. Il est officiel donc reconnu. Il est unique personne d’autre que vous ne peut utiliser ce badge.
La cryptographie asymétrique ( RSA et JWKS)
La cryptographie asymétrique utilise une paire de clés (une clé publique et une clé privée) pour sécuriser les communications. Dans le contexte d’OpenID Connect, les clés publiques sont souvent publiées dans un document JWKS (JSON Web Key Set), permettant aux clients de vérifier la signature des JWT émis par le fournisseur d’identité.
Le flux OIDC standard
Le flux OIDC standard implique plusieurs étapes clés, notamment l’authentification de l’utilisateur, l’autorisation et l’obtention d’un token d’accès. Ce processus garantit que les utilisateurs peuvent se connecter en toute sécurité à des applications tierces tout en protégeant leurs informations d’identification.
Third-Party Initiated Login
Imaginons un instant que LTI utilise un flow OIDC classique. Le LMS agirait alors comme client OIDC, et déléguerait l’authentification à un fournisseur d’identité. C’est le flow standard d’OpenID Connect, cela implique que l’apprenant a un compte ailleurs. Par exemple, lorsque je veux me connecter sur une plateforme qui offre la possibilité de se connecter avec un SSO, disons Google ou Microsoft. Je peux alors me connecter à la plateforme avec Google ou Microsoft mais cela implique que j’ai un compte chez Google ou Microsoft. Le login est initié par la plateforme qui en fait la demande et reçoit les informations nécessaires de Google ou Microsoft (pour cet exemple) pour m’identifier. C’est exactement ce que veut éviter LTI. En effet, c’est le LMS qui connaît l’apprenant, il est donc `fournisseur d’identité (IDP) et non un outil tiers. C’est le LMS qui détient les comptes, c’est lui le fournisseur d’identité. L’outil tiers, lui, a besoin de savoir qui est l’apprenant mais il n’a aucun moyen de le savoir tout seul. C’est le problème : l’outil tiers ne peut pas non plus initier le flux de lui-même. Il ne sait pas qu’un apprenant veut accéder à une ressource tant que le LMS ne le lui dit pas. C’est là qu’intervient le Third-party Initiated Login.
Le LMS redirige le navigateur de l’apprenant vers l’outil tiers, en lui envoyant des paramètres comme iss (pour Issuer qui dit à l’outil quel LMS lui parle), login_hint (pour identifier l’apprenant) et target_link_uri (la ressource à afficher). L’outil reçoit cette redirection. Il sait maintenant qu’un apprenant veut accéder à quelque chose, et il sait quel LMS est à l’origine de la demande. Il redirige alors le navigateur vers le LMS pour lui demander un jeton d’identité. Le LMS vérifie tout et renvoie le jeton d’identité à l’outil. L’outil peut maintenant afficher la ressource à l’apprenant.
Dans le cas classique, l’utilisateur clique sur un bouton et est redirigé vers Google. Dans le cas LTI, l’apprenant est déjà connecté au LMS et ne fait aucune action de login. C’est le LMS qui pousse le navigateur vers l’outil. Tout est transparent pour l’apprenant. La liste des paramètres du Third-party Initiated Login est disponible ici
OpenID Discovery
De manière générale, la configuration du flux ou perdre du connect nécessite un échange d’informations, souvent manuellement entre les deux parties. OpenID Connect Discovery offre un mécanisme d’autoconfiguration qui permet à un client de trouver automatiquement tous les détails nécessaires pour interagir avec un fournisseur d’identité.
L’identity provider fournit une URL et le client va pouvoir retrouver toutes les informations utiles à partir de cette URL.
- La recherche de l’issuer : Ici, OpenID Discovery utilise le protocole Webfinder. C’est une étape optionnelle.
- La recherche du document de configuration : Le client suffixe l’URL du fournisseur par cette adresse /.well-known/openid-configuration et récupère un document JSON qui contient toutes les informations nécessaires pour interagir avec le fournisseur d’identité, notamment les endpoints pour l’authentification, la tokenisation, la clé publique pour vérifier les signatures des JWT, etc.
Pour la liste complète des attributs de la réponse, je vous envoie sur la spécification d’OpenID Discovery.
OpenID Connect Dynamic Client Registration
OpenID Connect Dynamic Client Registration permet à un client de s’enregistrer dynamiquement auprès d’un fournisseur d’identité sans intervention manuelle. Le client envoie une requête POST au endpoint de registration du fournisseur avec les détails de son application (comme le nom, l’URL de redirection, etc.) et reçoit en retour un client_id et éventuellement un client_secret qui lui permettront de s’authentifier auprès du fournisseur d’identité lors des échanges ultérieurs.
Le Bearer Token pour les services LTI
Dans LTI1.3 il y a la notion de Message, c’est-à-dire un format standardisé pour échanger des informations entre le LMS et l’outil. Lti Advantage ajoute une notion de services qui partagent le même mécanisme pour sécuriser leurs appels HTTP. L’outil va pouvoir bénéficier de ces services en effectuant des requêtes vers le LMS en plus du flow LTI standard décrit dans l’article précédent.
Une fois que le flow standard LTI1.3 est terminé, l’échange entre le LMS et l’outil se fait à l’aide d’un access Token obtenu via le protocole OAuth 2.0. L’outil doit inclure ce token dans les en-têtes de ses requêtes HTTP pour accéder aux services proposés par le LMS. Les services disponibles dépendent des autorisations accordées à l’outil lors de la configuration de l’intégration.
Lors de la registration, l’outil doit demander l’URL pour obtenir un access token, c’est à dire l’URL du service d’autorisation du LMS. Cette URL est ensuite utilisée pour obtenir un access token.
Le flux se déroule en deux étapes :
- L’outil construit et signe un JWT avec sa clé privée
- L’outil poste ce JWT au token endpoint du LMS et reçoit en retour un access_token
Étape 1 — construire le client_assertion
L’outil crée un token JWT qu’il signe lui-même avec sa clé privée RSA (la même que celle déclarée lors de la registration). Ce JWT s’appelle le client_assertion.
Header :{ "alg": "RS256", "typ" : "JWT",}
Payload :{ "iss": "tool.com", "sub": "Sfc6HFnwHAx4Tuv", "aud": "http://localhost/mod/lti/token.php", "iat": 1775400958, "exp": 1775401018, "jti": "a3f1c2d4-e5b6-7890-abcd-ef1234567890"}iss: L’identifiant de l’outilsub: Le client idaud: L’URL du service d’autorisation du LMSiat: La date de création du JWT (Timestamp)exp: La date d’expiration du JWT (Timestamp)jti: Un identifiant unique pour le JWT
Étape 2 — Obtenir le Bearer token
L’outil envoie une requête POST au token endpoint du LMS avec le client_assertion dans le corps de la requête. Si la requête est valide, le LMS renvoie un access_token que l’outil peut utiliser pour accéder aux services protégés.
Exemple de requête :
POST http://localhost/mod/lti/token.phpContent-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vbi1raWQifQ...&scope=https://purl.imsglobal.org/spec/lti-ags/scope/scoreDans cet exemple http://localhost/mod/lti/token.php correspond à l’URL du service d’autorisation du LMS fournie au moment de la registration.
Ici, il ne s’agit plus d’authentifier un utilisateur mais d’authentifier l’outil lui-même.
Vous trouverez plus de détails dans la spécification sur la sécurité ici.