Accueil > OpenID Connect OAuth Serveur dédié > Développer > Incorporer au jeton JWT des déclarations supplémentaires

Incorporer au jeton JWT des déclarations supplémentaires

Les spécifications d’OAuth 2.0 autorisent l’ajout de nouvelles déclarations (claims) à la charge utile du jeton JWT.
Cet article montre comment cela est réalisé dans le cadre d’OAuthSD.

Cas d’usage

Il convient de s’assurer que l’utilisateur final est bien habilité à accéder à des ressources protégées, qu’il s’agisse de données personnelles ou que l’application soit propriétaire des données. On voudrait également pouvoir contrôler les données transmises par une ressource protégée à une application en fonction des droits de l’utilisateur final dans cette application.

Les administrateurs aussi bien que les utilisateurs finaux utiliseront OpenID Connect pour s’authentifier sur une application. On voudra donc moduler les droits et privilèges de l’utilisateur final en fonction de son identité, de son appartenance ou de son profil. L’exemple le plus simple est la distinction entre des droits de lecture des données et des droits de modification. On peut également envisager d’attribuer à l’utilisateur des droits d’administration de tout ou partie d’une application.

Ce n’est pas le rôle du serveur d’authentification, qui se doit d’être transparent par rapport aux portées d’autorisation (scopes) mis en oeuvre par une application. Pour cela, OAuthSD permet à une application externe d’incorporer des déclarations supplémentaires aux jetons JWT, qu’il s’agisse d’un jeton d’accès au format JWT ou d’un jeton d’identité. Les ressources protégées "sauront" interpréter les données du JWT pour contrôler leur réponse.

Remarque quant à la sécurité des données

Rappelons que la charge utile du jeton JWT n’est pas cryptée, mais seulement "URL64-encoded". Il convient donc de ne pas transmettre de cette façon des données sensibles.

L’intérêt de passer des données supplémentaires dans la charge utile du jeton JWT est de les lier de façon infalsifiable à l’identité du client et à celle de l’utilisateur à l’aide de la signature. Cela est particulièrement pertinent pour transmettre les privilèges d’un utilisateur ou d’une application à une ressource protégée. Dans cette optique, on peut :
- soit transmettre directement les privilèges ; par exemple un rôle qui prendrait des valeurs telles que ’administrateur’, ’redacteur’, ’propriétaire’, ’utilisateur’, etc., ou tout autre code compris par la ressource,
- soit transmettre les informations sur l’utilisateur qui permettront à la ressource protégée d’établir ses privilèges.

Mais attention dans ce deuxième cas : il ne faudra pas dévoiler de données sensibles sur l’utilisateur. Si la transmission de telles données à la ressource protégée s’avérait indispensable, la ressource protégée pourra interroger le service Userinfo.
On pourrait penser à un jeton crypté (JWE), mais cela nécessiterait, outre un développement spécifique, de s’écarter du standard OpenID Connect. Il serait beaucoup plus simple de crypter les informations supplémentaires en un seul bloc et de les passer dans une déclaration unique.

Il faut également faire attention à ne pas dépasser la longueur admise pour un JWT (à préciser).

Transmission de privilèges de l’utilisateur final avec l’authentification

OAuthSD offre deux méthodes complémentaires pour incorporer dans le JWT des informations relatives à un utilisateur final :

- l’écriture de données supplémentaires dans les champs ’profile’ et ’scope’ de la table users à l’aide du service HTTP Rest. Il s’agit d’un processus asynchrone dans la mesure où les données sont inscrites à un moment choisi par une application extérieure, indépendamment de l’interrogation du serveur d’autorisation.

OAuthSD utilise l’étendue d’autorisation (scope) "privileges" pour contrôler l’accès à ces informations. Quand une application présente le scope ’privileges’ dans la demande d’autorisation, les déclarations ’profil’ et ’scope’ sont inscrites dans la réponse Userinfo ainsi que dans la charge utile du jeton JWT. L’accès à l’API HTTP REST + TreeQL donne un bon exemple de transmission de privilèges.

- l’incorporation de données supplémentaires rafraîchies au moment de la fabrication du jeton JWT, par exemple en interrogeant un service externe. Il s’agit d’un processus synchrone ou de "scope dynamique", permettant d’obtenir des informations en phase avec celles détenues par les applications de gestion des utilisateurs dans le cas où cette gestion est extérieure au serveur.

Cette deuxième méthode est développée maintenant.

Incorporer des données supplémentaires à la charge utile du jeton JWT

Cette fonctionnalité est propre à une utilisation d’OAuthSD dans un groupe d’applications maîtrisées par une même organisation (Corporate Realm).

La bibliothèque oauth2-server-php offre une fonction reconfigurable pour insérer des déclarations supplémentaires dans un JWT au moment de sa création (depuis la version 1.10.0).

Pour incorporer des données supplémentaires, il faut :
- fixer la constante de configuration EXTRA_PAYLOAD à ’true’.
- définir le contenu de la fonction extra_payload() du fichier /oidc/interface/extrapayload.php.
La fonction extra_payload() doit être écrite par le concepteur des applications. Ce peut être un appel à un webservice tiers. La fonction reçoit les paramètres client_id, user_id et scope et doit retourner un array de ’claim’ => ’valeur’ qui sera combiné avec les déclarations de la charge utile sans pouvoir remplacer les déclarations standard.

Notes :
- Cette méthode permet de créer des déclarations ayant un nom quelconque. Cependant, les déclarations standard d’OIDC (’id’, ’jti’, ’iss’, ’aud’, ’sub’, ’exp’, ’iat’, ’token_type’ et ’scope’) ne pourront être surchargées : elles garderont leur nom et leur valeur. Si une déclaration ’scope’ est retournée, elle sera incorporée à la charge utile du JWT sous le nom "extra_scope".

- Les informations sont rafraîchies au moment de la création du jeton JWT ou de son rafraîchissement. Cela implique que ces informations ne sont pas strictement synchrones de leur correspondantes dans le système extérieur. Si les droits d’un utilisateur changent dans le système extérieur, il conviendra de révoquer la session de l’utilisateur afin de provoquer une nouvelle demande d’authentification ce qui entraînera la création d’un nouveau jeton JWT. Mais dans le cas où il serait nécessaire de modifier un grand nombre d’utilisateurs, une autre façon d’assurer le synchronisme sera de fermer le service le temps de la durée de vie d’un JWT.

- Cette méthode n’écrit pas dans la table users et, en particulier, dans le champ "scope". Si les déclarations supplémentaires comprennent une déclaration "scope" (ce qui sera généralement le cas), la valeur du champ "scope" de la table users sera incorporée à la charge utile du JWT sous le nom "user_scope".

- Dans tous les cas, la valeur du paramètre ’scope’ passé à l’appel d’authorize par l’application sera incorporé sous le nom ’requested_scope’ [1].

Voyez ci-dessous le code d’un exemple extrayant d’un web-service des données supplémentaires.

Il existe des informations complémentaires, connectez vous pour les voir.

Notes

[1Le nom "scope" est malheureusement utilisé par Oauth 2.0 pour des concepts différents. Il est donc naturel d’utiliser des noms différents pour éviter de mélanger ou d’écraser des données.