Demande d’informations sur l’utilisateur (UserInfo Endpoint)

, par DnC

Le point d’extrémité UserInfo du protocole OpenID Connect permet d’obtenir des informations sur l’utilisateur final authentifié.

Point d’extrémité UserInfo

L’URI est la suivante :

https://oa.dnc.global/userinfo

Forme de la demande UserInfo

La méthode de transmission recommandée pour la requête UserInfo est HTTP Auth Header :

 GET /userinfo HTTP/1.1
 Host: oa.dnc.global/userinfo
 Authorization: Bearer SlrqTTP7i88GkKGQWDbPs9RWVAnWHz5e7nxAV32hH

Exemples :

PHP

  1. // Méthode Auth Header
  2.  
  3. $h = curl_init('https://oa.dnc.global/userinfo');
  4. curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
  5. curl_setopt($h, CURLOPT_TIMEOUT, 10);
  6. curl_setopt($h, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $access_token));
  7.  
  8. $res = curl_exec($h);
  9. if (!$res)
  10.  
  11. $res = json_decode($res, true);
  12.  
  13. echo "UserInfo Response:\n";
  14. print_r($res);

Télécharger

SPIP

  1. $url = "https://oa.dnc.global/userinfo";
  2. $options = array(
  3. 'methode' => 'GET',
  4. 'datas' => 'Authorization: Bearer ' . $access_token,
  5. );
  6. $resource_response = recuperer_url($url, $options);

Télécharger

Exemple de requête avec la méthode POST. Notez que le jeton d’accès est fourni sans l’indication ’Bearer’ :
PHP

  1. // Méthode Post
  2.  
  3. $data2 = array(
  4. 'access_token' => $access_token,
  5. );
  6. $h = curl_init($userinfo_endpoint);
  7. curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
  8. curl_setopt($h, CURLOPT_TIMEOUT, 10);
  9. curl_setopt($h, CURLOPT_POST, true);
  10. curl_setopt($h, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded')); // semble facultatif : curl le fait pour nous?
  11. curl_setopt($h, CURLOPT_POSTFIELDS, http_build_query($data2));
  12. //*/

Télécharger

Réponse du serveur

En cas de succès, le serveur retourne une réponse HTTP 200.

Le corps de la réponse contient un tableau portant les informations suivantes :

index type valeur
status entier code HTTP
headers string Headers de la réponse
page string JSON Array :
La réponse est détaillée ici : Réponse UserInfo.

Note :
- La valeur (string) "null" est forcée pour tous les champs vides ou NULL.
- La spécification indique qu’il n’est pas garanti que la réponse UserInfo corresponde à l’utilisateur identifié par l’élément user_id du Token ID. Avant de considérer la réponse UserInfo comme valide, il convient de vérifier que la revendication user_id dans la réponse UserInfo Endpoint correspond exactement à la revendication user_id dans le Token ID.

 

En cas d’échec, le corps de la réponse contient :

index type valeur
page string JSON Array :
error : (string) titre de l’erreur,
error_description : (string) description de l’erreur

La réponse HTTP ainsi que les valeurs de error et error_description sont données par le tableau suivant :

Réponse error titre de l’erreur error_description description de l’erreur Explication
400 invalid_request Only one method may be used to authenticate at a time (Auth header, GET or POST) N’utiliser qu’une seule méthode d’authentification à la fois.
400 invalid_request Malformed auth header La requête de type Auth header est mal formée
400 invalid_request When putting the token in the body, the method must be POST or PUT Si on place le token dans le corps de la requête, la méthode ne peut être que POST ou PUT
400 invalid_request The content type for POST requests must be "application/x-www-form-urlencoded l’IETF spécifie ce type de contenu. NB : tous les serveurs Web ne remplissent pas cette variable _SERVER voir http://tools.ietf.org/html/rfc6750#section-2.2
401 (vide) (vide) La requête ne comporte aucune authentification
401 invalid_token The access token provided is invalid Le jeton ne figure pas dans le tokenStorage du serveur. Très probablement une tentative de violation d’accès.
401 expired_token The access token provided has expired Le jeton a expiré. L’application doit obtenir un nouveau jeton et relancer la requête
401 malformed_token Malformed token (missing "expires"
401 malformed_token Malformed token (missing "client_id")
403 insufficient_scope The request requires higher privileges than provided by the access token L’application cliente n’a pas été inscrite avec le scope openid

Réponse UserInfo

, par DnC

Le protocole OpenID Connect définit des informations de profil standard devant être retournées en réponse à une requête UserInfo.
Il permet également d’étendre ces données pour répondre aux besoins d’applications clientes spécifiques. OAuth Server by DnC propose un jeu étendu.
Cependant, il convient de définir avec soin les informations qui relèvent d’un serveur d’authentification et celles qui devraient être servies à part.

Informations de profil standard

La spécification de UserInfo dans le standard OpenID Connect figure ici : UserInfo Response

Dans l’état actuel du développement, OAuth Server by DnC fournit les déclarations (claims), autrement dit informations de profil, suivantes en fonction du scope :

Scope Informations de profil (claims)
profile name, family_name, given_name, middle_name, nickname, profile, picture, website, gender, birthday, zoneinfo, locale, updated_at
email email, verified
address address, street_address, locality, region, postal_code, country
phone phone_number

[dnc2]

Notes :
- La spécification indique qu’il n’est pas garanti que la réponse UserInfo Endpoint corresponde à l’utilisateur identifié par l’élément user_id du Token ID [1]. Avant de considérer la réponse UserInfo comme valide, il convient de vérifier que la déclaration user_id dans la réponse UserInfo Endpoint correspond exactement à la revendication user_id dans le Token ID.
- La revendication sub est toujours incluse dans la réponse.

Informations de profil étendu

La définition standard des couples scope-claims n’est pas satisfaisante pour deux raisons principales :
- le scope profile appelle trop d’informations, mélangeant des information essentielles et légitimement acceptables par l’utilisateur final avec des informations secondaires et plus intimes, telles que gender et birthdate.
- à l’inverse, plus d’informations sur l’utilisateur devraient être disponibles.

La norme permettant de définir des scope et des claims additionnels, une implémentation spécifique d’OAuth Server by DnC pourrait exposer de nouveaux couples scope-claims mieux appropriés :

Scope Informations de profil (claims)
job job_title, job_street_address, job_locality, job_region, job_postal_code, job_country, job_phone, job_phone2, job_mobile, job_fax, job_email, job_website
firm firm_name, firm_street_address, firm_locality, firm_region, firm_postal_code, firm_country, firm_phone, firm_phone2, firm_mobile, firm_fax, firm_email, firm_website
trading legalidentity, siret, rcs, vat_id, terms, rights

Jusqu’où étendre les informations de profil ?

On pourrait souhaiter que l’administrateur puisse définir, au moment de l’enregistrement de son application cliente sur le serveur d’autorisation, le jeu de données UserInfo qui corresponde aux besoin de son application.

On pourrait alors imaginer deux situations :
- l’administrateur confie les données UserInfo complémentaires au serveur d’authentification ;
- l’administrateur désigne un Web Service responsable de la délivrance des données UserInfo complémentaires. Le serveur d’autorisation s’adresserait alors à ce web service pour obtenir ces informations.

La deuxième solution a quelque chose d’absurde : pourquoi ne pas s’adresser directement au web service, puisque OAuth est là pour gérer l’autorisation nécessaire ? Par exemple, des informations du type des suivantes, utiles à une application eCommerce, devraient être servies à part :

Scope Informations de profil (claims)
delivery delivery_fullname, delivery_street_address, delivery_locality, delivery_region, delivery_postal_code, delivery_country, delivery_phone, delivery_infos
billing billing_fullname, billing_street_address, billing_locality, billing_region, billing_postal_code, billing_country, billing_phone, billing_vat_id
bank bank_name, bank_full_address, bank_bic, bank_iban

Cela permettrait également de séparer des données dont les scopes et noms sont ambigüs, telle que bank dans nos exemples.

Du coup, si cela est si facile de s’adresser à un service web pour obtenir des informations complémentaires sur l’utilisateur, quant à la première solution, on peut aussi se demander s’il est légitime de confier les informations les plus diverses au serveur d’authentification. En effet, ce n’est pas à cela que sert un tel serveur.

S’agissant de OAuth Server by DnC, si nous pensons étendre les informations de profil avec les jetons job, firm, bank et trading, cela correspond bien à la mission du serveur d’authentification de fournir des informations suffisantes pour consolider la confiance que l’on peut avoir dans l’identité de l’utilisateur final. Il ne faudrait donc pas étendre au delà les informations de profil stockées sur le serveur d’authentification [2]

En revanche, un serveur d’authentification dédié à un groupe d’applications et de ressources données (tel que le sont les serveurs OAuth mis en oeuvre par G..., F... etc.) pourrait avantageusement compléter son jeu de données utilisateur. C’est exactement ce que fait Wordpress avec le jeton blog.

Chez DnC, nous pensons qu’une telle approche est parfaitement justifiée, et nous souhaitons développer ce type d’application pour nos clients.

Utilisation du scope "profile" claim "profile" pour l’attribution de privilèges dans les applications

La spécification permet à une application "d’obtenir l’accès en son propre nom". On ne parlera plus de ressource protégée appartenant à l’utilisateur final, mais de ressource appartenant à l’application ou à l’organisation qui en est propriétaire.

Dans ce paradigme, il convient de s’assurer que l’utilisateur final est bien habilité à accéder à des ressources protégées, et même de moduler ses droits et privilèges. 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 des droits d’administration de tout ou partie d’une application.

Le claim profile apparait dans le scope standard profile. OpenID Connect n’impose pas un usage particulier de ce claim. Il parait tout indiqué pour attacher des privilèges à un utilisateur final.

Deux points doivent être soulignés :

- OAuthSD regroupe les informations sur l’utilisateur final dans la table users. Le champ profile est du type texte et peut donc accueillir toute sorte de données pour décrire le profil de l’utilisateur ou donner la liste de ses privilèges.
Rappelons que le serveur d’authentification est transparent par rapport aux claims : c’est à la ressource protégée de définir ce qui doit en être fait en fonction d’une application donnée. Il en résulte que le format du claim profile et son contenu ne peut être défini que dans le cadre d’une application donnée.

- Le contenu du champ profile peut être connu de l’utilisateur final, mais celui-ci ne doit pas pouvoir en modifier le contenu. En conséquence, le champ profile est réservé à l’administrateur de l’application.

Notes

[1Pourquoi ?

[2Avertissement : depuis la mise en application du RGPD, il convient d’observer les règles de protection des données personnelles. Cette question est hors du champ de ce site. Voir en particulier le site de la CNIL.