Documents de référence

  publie le par DnC

Documents essentiels

Synthèse : OAuth 2.0
Code : Brent Shaffer’s OAuth Server PHP

Documents de l’IETF

-  RFC 6749 L’architecture d’authentification OAuth 2.0.
L’architecture d’autorisation OAuth 2.0 permet à une application tierce d’obtenir un accès limité à un service HTTP, soit au nom d’un propriétaire de ressource en orchestrant une interaction d’approbation entre le propriétaire de la ressource et le service HTTP, soit en autorisant l’application tierce à obtenir l’accès en son propre nom.

- RFC 7523 JSON Web Token (JWT) Profil pour les soumissions d’authentification et d’autorisation de client OAuth 2.0.
Cette spécification définit l’utilisation d’un JSON Web Token (JWT) Bearer Token comme moyen de demander un jeton d’accès OAuth 2.0 ainsi que pour l’authentification du client.

- RFC 7516 JSON Web Encryption (JWE)
JSON Web Encryption (JWE) représente du contenu chiffré basé sur JSON. Les algorithmes cryptographiques et les identificateurs à utiliser avec cette spécification sont décrits dans le document JSON Spécification des Algorithmes Web (JWA) et registres IANA définis par cette spécification. En relation, la signature numérique et les capacités du Code d’Authentification de Message (MAC) sont décrites dans le document séparé Spécification JSON Web Signature (JWS).

- RFC 7515 JSON Web Signature (JWS)
JSON Web Signature (JWS) représente du contenu sécurisé par signature numérique ou des codes d’authentification de message (MACs) utilisant des structures de données basées sur JSON. Les algorithmes cryptographiques et les identificateurs à utiliser avec cette spécification sont décrits dans le document JSON Web Algorithmes (JWA) et un registre IANA défini par la spécification. Les capacités de cryptage associées sont décrites par la spécification distincte JSON Web Encryption (JWE).

- RFC 7662 OAuth 2.0 Token Introspection
Cette spécification définit une méthode permettant à une ressource protégée d’interroger un serveur d’autorisation OAuth 2.0 pour déterminer l’état actif d’un jeton OAuth 2.0 et pour déterminer des méta-informations sur ce jeton.
Les déploiements OAuth 2.0 peuvent utiliser cette méthode pour transmettre à la ressource protégée des informations sur le contexte d’autorisation du jeton à partir du serveur d’autorisation.

-  RFC 7009 OAuth 2.0 Token Revocation.
Ce document propose un point d’extrémité supplémentaire pour le serveur d’autorisation OAuth, qui permet aux clients d’avertir le serveur d’autorisation qu’un jeton de rafraîchissement ou d’accès précédemment obtenu n’est plus nécessaire. Cela permet au serveur d’autorisation de nettoyer les données de sécurité. Une demande de révocation invalidera le jeton en question et, le cas échéant, d’autres jetons basés sur la même autorisation.

OpenID Connect

La référence : OpenID Connect.

OpenID Connect Core 1.0 incorporating errata set 1
OpenID Connect 1.0 est une couche d’identité simple fondée sur le protocole OAuth 2.0. Il permet aux clients de vérifier l’identité de l’utilisateur final en fonction de l’authentification effectuée par un serveur d’autorisation, ainsi que d’obtenir des informations de profil de base sur l’utilisateur final de manière interopérable et REST.
Cette spécification définit la fonctionnalité de base OpenID Connect : authentification construite sur OAuth 2.0 et l’utilisation de revendications pour communiquer des informations sur l’utilisateur final. Il décrit également les considérations de sécurité et de confidentialité pour l’utilisation d’OpenID Connect.

OpenID Connect Basic Client Implementer’s Guide 1.0 - draft 37
OpenID Connect 1.0 est une couche d’identité simple fondée sur le protocole OAuth 2.0. Il permet aux clients de vérifier l’identité de l’utilisateur final en fonction de l’authentification effectuée par un serveur d’autorisation, ainsi que d’obtenir des informations de profil de base sur l’utilisateur final de manière interopérable et REST.
Ce Guide d’implémentation OpenID Connect Basic Client 1.0 contient un sous-ensemble de la spécification OpenID Connect Core 1.0 conçue pour être facile à lire et à implémenter pour les échanges entre applications Web basés sur le flux d’autorisation OAuth. Ce document double intentionnellement le contenu de la spécification Core pour fournir un guide d’implémentation autonome pour des développements d’applications Web élémentaires utilisant le flux de code d’autorisation OAuth.
Les fournisseurs OpenID et les applications non Web doivent plutôt consulter la spécification Core.

Documents de Microsoft Exchange

Exchange 2013 utilise un jeton JWT (JSON Web Token) pour le jeton d’identité. La documentation technique d’Exchange appelle "Jeton d’identité" quelque chose de très similaire à l’ID Token défini par OpenID Connect. Il est donc intéressant de consulter les documents suivants :

- Présentation du jeton d’identité Exchange

- Utilisation de PHP pour valider un jeton d’identité

Envoi d’une requête à une ressource protégée

  publie le par DnC

Dans cet article, nous traitons de l’accès à une ressource protégée de type HTTP REST, avec les bonnes pratiques.

Envoi d’une requête à une ressource protégée

Il y a trois méthodes pour l’envoi d’une requête à une ressource protégée : une bonne, une acceptable et une non recommandée :

Ce qui suit est pour l’essentiel une traduction de parties de la RFC 6750, section 2

2. Requêtes authentifiées

Cette section définit trois méthodes d’envoi de jetons d’accès aux serveurs de ressources. Les clients NE DOIVENT PAS utiliser plus d’une méthode pour transmettre le jeton dans chaque requête.

2.1. Demande d’autorisation par Champ d’en-tête (la bonne méthode)

Lors de l’envoi du jeton d’accès par l’en-tête de la requête (Request Header) dans le champ "Authorization" défini par HTTP / 1.1 [RFC2617], le client utilise le schéma d’authentification "Bearer" pour transmettre le jeton d’accès.
Par exemple :

    GET / resource HTTP / 1.1
    Host: oa.dnc.global
    Authorization: Bearer mF_9.B5f-4.1JqM

Exemples :

PHP

  1. $h = curl_init('https://oa.dnc.global/userinfo');
  2. curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
  3. curl_setopt($h, CURLOPT_TIMEOUT, 10);
  4. curl_setopt($h, CURLOPT_HTTPHEADER,
  5. array('Authorization: Bearer '
  6. . $access_token));
  7. $res = curl_exec($h);

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. $res = recuperer_url($url, $options);

Télécharger

Les clients DOIVENT faire des requêtes authentifiées avec un jeton Bearer en utilisant le champ d’en-tête de demande « Authorization » avec le schéma d’autorisation du protocole HTTP « Bearer ». Les serveurs de ressources DOIVENT supporter cette méthode.

2.2. Paramètres form-urlencoded dans le corps (une méthode acceptable)

Lors de l’envoi du jeton d’accès dans le corps d’entité de requête HTTP, le Client ajoute le jeton d’accès au corps de requête en Paramètre "access_token". Le client NE DOIT PAS utiliser cette méthode à moins que toutes les conditions suivantes sont remplies :
- L’entête d’entité de requête HTTP inclut le champ d’en-tête "Content-Type" "application / x-www-form-urlencoded".
- Le corps de l’entité suit les exigences d’encodage du type de contenu "Application / x-www-form-urlencoded" tel que défini par HTML 4.01 [W3C.REC-html401-19991224].
- Le corps de l’entité de demande HTTP est mono-partie.
- Le contenu codé dans le corps de l’entité DOIT se composer entièrement de d caractères ASCII [USASCII].
- La méthode de requête HTTP suit la sémantique définie pour le corps de requête. En particulier, cela signifie que la méthode "GET" NE DOIT PAS être utilisée.

Le corps de l’entité PEUT inclure d’autres paramètres spécifiques aux requêtes, auquel cas le paramètre "access_token" DOIT être correctement séparé des paramètres spécifiques à la requête en utilisant le caractère "&" (ASCII Code 38).

Par exemple, le client effectue la requête HTTP suivante en utilisant la sécurité des couches de transport :

    POST / ressource HTTP / 1.1
    Host: oa.dnc.global
    Content-Type: application/ x-www-form-urlencoded
    access_token = mF_9.B5f-4.1JqM

La méthode "application/ x-www-form-urlencoded" NE DOIT PAS être utilisée sauf dans les contextes d’application où les navigateurs participants n’ont pas accès au champ d’en-tête de demande "Authorization". Les serveurs PEUVENT soutenir cette méthode.

Exemple :
PHP

  1. $data2 = array(
  2. 'access_token' => $access_token,
  3. );
  4. $h = curl_init($userinfo_endpoint);
  5. curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
  6. curl_setopt($h, CURLOPT_TIMEOUT, 10);
  7. curl_setopt($h, CURLOPT_POST, true);
  8. curl_setopt($h, CURLOPT_HTTPHEADER,
  9. array('Content-Type: application/x-www-form-urlencoded'));
  10. curl_setopt($h, CURLOPT_POSTFIELDS, http_build_query($data2));
  11. $res = curl_exec($h);

Télécharger

2.3. Paramètres de requête dans l’URI (la mauvaise méthode)

Lors de l’envoi du jeton d’accès dans l’URI de requête HTTP, le client ajoute le jeton d’accès au composant de requête de l’URI tel que défini par "Uniform Resource Identifier (URI) : Syntaxe générique" [RFC3986], en utilisant le paramètre "access_token".

Par exemple, le client effectue la requête HTTP suivante en utilisant la sécurité des couches de transport :

    GET /resource?access_token=mF_9.B5f-4.1JqM HTTP / 1.1
    Host: oa.dnc.global

...

Les clients utilisant la méthode URI Query Parameter DEVRAIENT également envoyer un entête Cache-Control contenant l’option "no-store". Les réponses de succès (status 2XX) du serveur à ces demandes Serveur DOIVENT contenir un entête Cache-Control avec l’option "private".

En raison des faiblesses de sécurité associées à la méthode URI (Voir la section 5), y compris la forte probabilité que l’URL contenant le jeton d’accès soit enregistrée, elle NE DOIT PAS être utilisée à moins qu’il soit impossible de transporter le jeton d’accès dans le champ d’en-tête de requête "Authorization" ou dans le corps d’entité de la requête HTTP. Les serveurs de ressources PEUVENT supporter cette méthode.

Cette méthode est incluse pour documenter une utilisation possible ; son utilisation n’est pas recommandée en raison de ses déficiences en matière de sécurité (voir section 5), mais également parce qu’elle utilise un nom de paramètre de requête réservé, ce qui est contraire aux meilleures pratiques de l’espace de noms URI, définies par « Architecture of the World Wide Web, Volume One" [W3C.REC-webarch-20041215]

Voir aussi :
- Validation du jeton d’accès par interrogation du serveur d’autorisation (Introspection)
- Contrôle d’accès HTTP (CORS)

Portée de l’autorisation (Scope)

  publie le par DnC

Les Scopes définissent l’étendue des droits (les actions permises sur les données de la ressource protégée) attachés au jeton d’accès qui est transmis par l’application cliente aux applications tierces (Serveurs de ressources). Celles-ci énumèrent les scopes attachés à l’autorisation ; elles ont la responsabilité d’agir en conséquence pour permettre ou non l’accès de l’application cliente aux données protégées.

Il est important de noter que les droits portés par un scope ne dépendent que de la façon dont l’application tierce en tient compte (ou non). Autrement dit, l’application tierce doit être une application de confiance, parfaitement identifiable par l’utilisateur final. De même, l’utilisateur final doit être authentifié. OAuth Server by DnC s’attache à apporter des solutions innovantes pour la qualification des applications et des utilisateurs, ce qui constitue une grande part de sa valeur ajoutée.

Définition

L’attribut "scope" est défini dans la section 3.3 de la [RFC6749].

L’attribut "scope" est une liste de valeurs sensibles à la casse, délimitées par des espaces, indiquant la portée requise du jeton d’accès pour accéder à la ressource demandée.

Les valeurs "scope" sont définies par l’implémentation ; il n’y a pas de registre centralisé pour eux ; les valeurs autorisées sont définies par le serveur d’autorisation.

L’ordre des valeurs "scope" n’est pas significatif.

Dans certains cas, la valeur "scope" sera utilisée lors de la demande d’un nouveau jeton d’accès avec une étendue d’accès suffisante pour utiliser la ressource protégée.

L’utilisation de l’attribut "scope" est OPTIONNELLE.

L’attribut "scope" NE DOIT PAS apparaître plus d’une fois.

Deux cas de figure

La norme OAuth 2.0 (RFC 6749) distingue deux cas de figure dans lesquels les scopes seront utilisés différemment :

1. L’utilisateur final est propriétaire des données protégées, et c’est donc lui qui autorise l’accès à ses données par les applications clientes tierces. Pour cela il sélectionne les scopes parmi ceux qui lui sont présentés au moment de la procédure d’autorisation. Le serveur de ressource ne doit permettre l’accès qu’aux ressources autorisées en fonction des scopes sélectionnés. [1].

2. L’application cliente est elle-même propriétaire des données situées sur les serveurs de ressources : elle autorise l’utilisateur final à accéder à ces données en son nom propre. Dans ce cas, les scopes sont définis par l’application cliente [2]. Il est important de considérer que cela donne à l’application cliente le moyen de moduler les autorisations selon le statut ou le profil de l’utilisateur, ce qui est un mécanisme très puissant puisque cette modulation de l’autorisation est propagée aux applications tierces.

Voyez également Identity by DnC qui apporte une solution innovante pour moduler les scopes selon le profil des utilisateurs.

La norme OAuth 2.0 ne donne pas un jeu de scopes prédéfini

OAuth définit les scopes et les mécanismes attachés de façon très générale. Rappelons que OAuth sert de base à différents protocoles qui en font un usage différent selon les applications.

Un jeu de scopes peut être défini à la fois pour segmenter un ensemble de données en sous-ensembles (diviser un profil en identité, adresse postale, données personnelle etc.), ou pour définir les actions (lecture, écriture, suppression etc.) permises sur les données, ou ces deux usages simultanément.
On voit qu’ils dépendent de la nature des ressources et de l’utilisation que pourraient en faire les applications clientes. Les scopes peuvent donc être très variés.

Un serveur OAuth suivant la norme OAuth 2.0 (comme c’est le cas de OAuth Server by DnC) doit donc être totalement transparent à leur définition et à leur usage :
- les scopes sont définis par le concepteur du serveur de ressources,
- c’est au serveur de ressource d’assurer le respect des autorisations définies par les scopes accompagnant le jeton d’accès au moment de la requête,
- les scopes qu’une application cliente peut utiliser sont librement définis au moment de son inscription sur le serveur d’autorisation.

Ceci a des conséquences très importantes :

- Soit les scopes ont une définition très générale, et le serveur de ressource peut répondre à des requêtes en provenance d’application clientes qui lui sont totalement étrangères,

- Soit les scopes ont une signification plus précise, et les serveurs de ressources comme les applications clientes doivent avoir une connaissance mutuelle. Cela peut se produire dans le cadre d’un protocole particulier, dans un ensemble particulier d’applications ou dans un espace contrôlé par une organisation (corporate realm).

OpenID Connect : une définition partielle des scopes

OpenID Connect est un protocole d’authentification construit sur OAuth.

Concernant les scopes, OpenID connect définit un jeu de scopes standards, adaptés à la fonction d’authentification de l’utilisateur final, mais permet également l’utilisation de scopes particuliers.

Notes

[1C’est souvent beaucoup plus simple que cela : l’application signale les scopes qu’elle demande, et l’utilisateur final termine la procédure si les données réclamées (claims) lui conviennent, ou il abandonne.

[2Ou plus généralement "par l’implémentation". En effet, le concepteur de l’application cliente définit les scopes en fonction de ce qu’elle attend et de ce qu’elle en fait. Mais les scopes autorisés pour une application cliente peuvent être utilisés ou non, assortis éventuellement d’un paramètre, en fonction des droits que l’on veut accorder à l’utilisateur final. Ceci peut aussi bien être déterminé par le serveur d’authentification au moment où l’on crée le jeton, en fonction de conditions extérieures à l’application cliente.

Définition des scopes et généralités sur leur utilisation par les applications

  (publie initialement le mercredi 6 décembre 2017) par DnC

La portée de l’autorisation est définie par les Scopes. C’est sans doute le point le plus ouvert du standard et donc un concept difficile à maîtriser pour le développeur d’une application utilisant OpenID Connect.

La possibilité de moduler les portées d’autorisation en fonction de l’application cliente et de l’utilisateur final est une fonctionnalité exceptionnellement intéressante d’OpenID Connect.

On voit souvent en OIDC un simple SSO, mais c’est passer à côté de toute la puissance du dispositif : le jeton d’identité JWT regroupe, de façon indissociable et infalsifiable, l’identité de l’utilisateur final, celle de l’application cliente et les portées d’autorisation.

Quatre niveaux de définition des scopes

1. Les Scopes pris en charge par le serveur (Supported scopes)

En plus des scopes réservés et non-réservés définis par OpenID Connect, l’administrateur définit les scopes particuliers utilisés par les applications. Ils sont inscrits dans le fichier de configuration du serveur (variable $supportedScopes).

Le scope ’basic’ est également inscrit dans la configuration en tant que scope par défaut.

Seuls ces scopes peuvent être utilisés, le contrôleur Authorize rejettant toute requête comprenant un scope absent de cette liste.

2. Les Scopes réservés (Reserved Scopes)

Les Scopes réservés jouent un rôle particulier [1]. Ils sont essentiellement utilisés par le serveur pour modifier le comportement des flux. Ils pourraient être interprétés par une application pour un usage particulier.

- openid : ce scope est obligatoire pour que l’application puisse fonctionner avec OpenID Connect. S’il est le seul scope demandé, l’identification de l’utilisateur final se réduira au claim sub.

- offline_access : Les demandes d’accès d’OpenID Connect incluent le jeton d’actualisation uniquement si la portée offline_access a été demandée et accordée.

- sli : ce scope est obligatoire pour que l’application accepte l’identification unique (Single Login Identification, SLI) et la ré-authentification silencieuse (Silent Re-Authentication, SRA) telles que nous les avons implémentées dans OAuthSD.

- kerberos : ce scope autorise la création d’une session SLI d’OAuthSD à partir de l’authentification avec Kerberos.

3. Les Scopes disponibles pour une application (Available scopes)

Ces scopes sont définis au moment de l’inscription d’une application sur le serveur. Ils comprennent :
- tout ou partie des scopes réservés,
- des scopes non-réservés (Non Reserved Scopes), qui sont définis par OpenID Connect ou définis à l’initiative du concepteur de l’application.

4. Les portées accordées (Granted scopes)

Une application transmet les scopes dans la demande d’autorisation (appel au point de terminaison Authorize). Ils doivent figurer dans la liste des Scopes disponibles pour une application définie précédemment.

Il faut considérer les scopes selon deux cas de figure [2] :
- soit les données protégées sont la propriété de l’utilisateur, et les scopes doivent être compris comme une demande d’accès de l’application à ces données : l’application devra obtenir l’accord de l’utilisateur pour poursuivre,
- soit l’application (au sens large) "possède" les données protégées, et les scopes doivent être compris comme une portée consentie par l’application.

Dans le deuxième cas (si les données appartiennent à l’application) une application peut moduler les scopes accordés à l’utilisateur, en fonction de son profil.

Si l’application ne prévoit pas de moduler les scopes accordés, le concepteur peut utiliser les scopes autorisés ou le scope par défaut.

Une fois l’authentification réalisée, les scopes deviennent des portées accordées (granted scopes).

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

Notes

[1Tellement particulier qu’ils n’ont rien à voir avec une portée d’autorisation, mais nous apparaissent plutôt comme un moyen de paramétrer les flux. Il y a peut-être là un défaut conceptuel d’OpenID Connect ?

[2Comme prévu par la norme : voir Portée de l’autorisation (Scope).

[3Dans l’état actuel du développement, cette fonctionnalité n’est implémentée que dans le cadre du flux Authorization Code.

[4Dans l’état actuel du développement, cette fonctionnalité n’est implémentée que dans le cadre du flux Authorization Code.

Demandes de consentement sur les portées d’autorisation (scopes)

  publie le par DnC

Le règlement général sur la protection des données (RGPD) impose une gestion rigoureuse des données personnelles ce qui implique de demander à leur propriétaire l’autorisation d’y accéder.
Quels sont les cas de figure à distinguer ?
Comment gérer les demandes de consentement sur les portées d’autorisation à bon escient, sans lourdeur ni répétition inutile ?


Demande de consentement : différents cas de figure

Dès leur origine, OAuth et OpenID Connect ont été pensés pour protéger les données sensibles appartenant à l’utilisateur final, à qui on demande l’autorisation d’y accéder. Le vocabulaire utilisé et les exemples donnés dans les spécifications sont fortement orientés par cette vision.

Cependant, la réalité des applications ne se limite pas à ce cas de figure : l’utilisateur de l’application peut être distinct du propriétaire des données. Heureusement, OpenID Connect offre un ensemble de techniques qui permettent de s’assurer que l’utilisateur final est bien celui qu’il prétend être et autoriser son accès à des ressources protégées ou des applications qui contiennent des données sensibles, lui appartenant ou non.

Toute la problématique du consentement réside dans la position de l’utilisateur final par rapport au propriétaire des données.

A - L’utilisateur final est connecté à une application qui travaille sur ses données personnelles.

C’est la situation qui a orienté la description d’OAuth et OpenID dès leur origine et qui imprègne fortement OpenID Connect avec les données UserInfo. Celles-ci sont segmentées par portée (scope) de façon à n’accéder qu’aux données nécessaires à un moment donné. La spécification permet de définir de nouveaux scopes et d’étendre les données personnelles.

Dans ce cas, il convient de présenter à l’utilisateur une demande de consentement pour chaque portée d’autorisation [1].

B - L’utilisateur final est connecté à une application à laquelle il fournit des informations personnelles auxquelles des tiers accéderont ultérieurement.

Il s’agit donc d’une application à laquelle des tiers authentifiés peuvent se connecter avec un rôle déterminé, leur permettant de consulter ou exploiter les données personnelles.

Ce cas peut être traité de la façon suivante :

B1 - Il est présenté à l’utilisateur final propriétaire des données un avertissement au moment où il entre dans l’application, libellé en tenant compte des scopes que l’application est susceptible d’utiliser.

B2 - Il est présenté une demande d’autorisation au moment où l’utilisateur introduit ses données personnelles dans l’application.

Nous pourrions mentionner aussi la solution de facilité qui consiste à :

B0 - faire approuver, avant toute utilisation, des conditions générales qui évoquent de façon plus ou moins détaillée les traitements effectués sur les données personnelles. Parfois, cette façon de faire ne distingue même pas le propriétaire des autres utilisateurs. Elle peut également être utilisée pour s’octroyer la dispense d’appliquer le cas A.

L’idéal serait de demander l’autorisation d’accès au cours de l’utilisation de l’application par un tiers : "Bonjour M. Dupont. M. Tournesol souhaite accéder à vos données scope1, scope2 etc. avec l’application Truc."

On pourrait imaginer :

B3 - un échange d’E-mail, avec toute la difficulté liée aux délai de réponse, voire à la non-réponse. On imagine difficilement faire cela au cours de chaque session. Il serait plus praticable de le faire périodiquement, ou lorsqu’une nouvelle application ou un nouvel agent souhaite accéder aux données.

B4 - Une application dans laquelle les deux parties sont connectées. C’est le cas d’une application à laquelle le propriétaire des données se connecte et échange avec un agent (par exemple un chat avec un conseiller) qui a besoin d’accéder aux données personnelles au cours de la conversation. Les demandes de consentement pourraient être présentées en temps réel à l’utilisateur final. C’est parfaitement possible, mais cela ne semble pas une pratique courante. Une difficulté réside dans le fait que l’on donnerait l’impression à l’utilisateur final que l’on s’interdirait d’accéder aux données personnelles en dehors de cette procédure.

La mise en oeuvre des demandes de consentement par OAuthSD

La plupart des cas de figure ci-dessus devront être traités différemment selon l’application. Tel quel, OpenID Connect offre les moyens de gérer ces situations au prix de nombreux aller-retours entre le serveur et l’application cliente, à laquelle il appartiendra de développer la logique.

Un des objectifs d’OAuthSD est de simplifier l’écriture des applications clientes en intégrant le plus possible de fonctionnalités dans le serveur d’authentification/autorisation.
Le cas A est le cas standard auquel OAuthSD répond conformément aux spécifications. Sans prétendre prendre totalement en charge chacun des autres cas présentés ci-dessus, OAuthSD offre des facilités décrites dans ce qui suit.

La gestion "standard" des consentements

La spécification d’OpenID Connect permet de traiter pleinement le cas A et offre des outils pour les autres cas.

Le paramètre d’URL scope détermine quelles sont les portées d’autorisation demandées par l’application cliente.
Seuls les scopes non-réservés feront l’objet d’une demande de consentement (les autres ont un caractère technique).

Notes :
- La notion de scope est un fourre-tout décrit ici : Définition des scopes et généralités sur leur utilisation par les applications.

La présentation de la demande de consentement dépend du paramètre d’URL prompt présent dans la requête passée au contrôleur Authorize [2].
- Si prompt est égal à ’none’ ou ’login’, aucun consentement n’est demandé à l’utilisateur final.
- Si prompt est omis [3], ou est égal à ’consent’ ou ’login consent’, les demandes de consentement sont présentées à l’utilisateur final.

Une bonne pratique de la gestion des consentements consiste à attendre pour les demander que l’application ait besoin d’accéder aux données correspondantes, et non systématiquement dès l’entrée dans l’application. Ceci se fait en appelant le contrôleur Authorize avec le paramètre prompt = ’consent’.
Cependant, si l’utilisateur n’est pas ou plus connecté à ce moment, il y aura un retour d’erreur. Pour éviter cela, il est recommandé d’autoriser le SLI pour l’application.

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

Notes

[1Faut-il demander à l’utilisateur de donner son consentement globalement pour tous les scopes qui lui sont présentés ou lui permettre de les approuver un à un ? Nous pensons que les scopes doivent être présentés à l’approbation juste au moment où l’application cliente a besoin d’accéder aux données correspondantes. A ce moment, refuser un scope parmi une liste de plusieurs entraîne le non fonctionnement de l’application, donc une approbation différenciée n’a pas de sens. Dans le formulaire d’approbation, OAuthSD ne présente donc que l’option d’accepter ou refuser globalement la liste présentée.

[3Ce comportement par défaut peut être modifié dans la configuration.

Contrôle d’accès HTTP (CORS)

  publie le par DnC

Les requêtes HTTP de type multi-origines (Cross-Origin Request) sont des requêtes pour des ressources localisées sur un domaine différent de celui qui est à l’origine de la requête.

C’est exactement la configuration dans laquelle nous nous trouvons quand nous voulons appliquer les protocoles d’authentification à la communication entre applications réparties sur Internet.

Du fait de nombreux abus (attaques de type cross-site request forgery ou CSRF), les requêtes HTTP croisées ont été sujettes à des restrictions pour des raisons de sécurité bien compréhensibles.

Le but de cet article et d’expliquer comment franchir ces restrictions en toute légitimité et sécurité dans le cadre de la mise en oeuvre du service OAuth Server by DnC.

Références :
- Contrôle d’accès HTTP
- Cross-Origin Resource Sharing
- Les attaques de type cross-site request forgery

Différents cas de figure

Comme toujours lorsque nous abordons la question de la communication entre applications réparties sur différents domaines, nous devons d’abord distinguer deux cas :
- les serveurs de ressources protégées (RS) sont interrogés par des applications clientes identifiées à l’avance ; c’est toujours le cas lorsque les applications et les RS appartiennent à une même organisation ;
- les RS n’ont pas une connaissance préalable des applications.

Le premier cas est trivial. L’autorisation des requêtes multi-origines (Cross-Origin Request) [1] pourra être donnée, par exemple si le service est publié par un serveur http Apache ou compatible, dans le fichier .htaccess du RS :

##### CORS pour monsite.com :
SetEnvIf Origin "^http(s)?://(.+\.)?monsite\.com$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is

Seul le deuxième cas mérite notre attention.

Autorisation après validation du jeton d’accès

Dans le deuxième cas (l’application cliente n’est pas connue du RS) notre solution consiste à inscrire le champ Access-Control-Allow-Origin dans la réponse du serveur de ressource (RS) si, et seulement si, le jeton a été validé auprès du serveur d’autorisation. Cela semble la bonne méthode, puisque le RS s’en remet au serveur d’autorisation pour réaliser toutes les vérifications nécessaires, et n’a donc pas besoin de connaître le domaine d’origine de la requête [2].

Voici un exemple de fonction d’autorisation en PHP pour SPIP 3.1, dans laquelle le RS valide le jeton par introspection (voir : Validation du jeton d’accès par interrogation du serveur d’autorisation (Introspection)) :

  1. /*
  2. Autorisation avec OAuth Server by DnC
  3. Auteur : Bertrand degoy
  4. Copyright (c) 2016 DnC
  5. */
  6.  
  7. function oauth_authorize($accesstoken) {
  8.  
  9. if ( !empty( $accesstoken ) ) {
  10.  
  11. // Interroger OAuth Server by DnC
  12. include_spip('inc/distant');
  13. // Vérifier le jeton d'accès (access token)
  14. $url = "http://oa.dnc.global/oauth/resource.php?access_token=" . $accesstoken;
  15. $res = recuperer_url($url);
  16. if ( (int)$res['status'] === 200 ) {
  17. if ( isset($_SERVER["HTTP_ORIGIN"]) ) {
  18. // Accès HTTP (CORS) : autoriser l'origine
  19. $issuer = trim(strtr($_SERVER["HTTP_ORIGIN"], '<>"\'', '[]##'));
  20. header('Access-Control-Allow-Origin', $issuer);
  21. }
  22. return true ;
  23. }
  24.  
  25. } else return false;
  26.  
  27. }

Télécharger

Tester : http://chemindeleau.com/?page=test-rpc-3 (utilise la fonction ProtectedApi_GET_auto() décrite ici : Une fonction pour tout simplifier !).

Cet exemple s’appuie sur l’API HTTP REST de Radar. Le site Chemin de l’eau est un site opérationnel qui met en œuvre des fonctionnalités issues des prototypes OAuthSD et Radar.

Message d’erreur : Blocage d’une requête multi-origines

"Blocage d’une requête multi-origines (Cross-Origin Request) : la politique « Same Origin » ne permet pas de consulter la ressource distante située sur http://r.dnc.global/http.api/collectionjson/gis?lat=47.8655638&lon=5.3314162&dmax=10&token=. Raison : échec du canal de pré-vérification des requêtes CORS."

La requête suivante, bien que le type indiqué soit ’GET’, est négociée avec la méthode ’OPTIONS’. Il en résulte que la requête cross-site est de type requête prévérifiée ("preflighted requests") :

  1. <div id="result"></div>
  2.  
  3. <script>
  4.  
  5. $.ajax({
  6.  
  7. url: 'http://r.dnc.global/http.api/collectionjson/gis',
  8. dataType: 'json',
  9. type: 'GET',
  10. contentType: 'application/json',
  11. data: 'lat=47.8655638&lon=5.3314162&dmax=10&token=#SESSION{auth_token}',
  12. timeout: 15000,
  13. success: function(data) {
  14. var text = '<b>Requete : ' + data.collection.href + '</b><br /><br />';
  15. items = data.collection.items;
  16. for (var i=0; i < items.length; i++ ) {
  17. for (var j=0; j < items[i].data.length; j++ ) {
  18. text += items[i].data[j].name + '=' + items[i].data[j].value + "<br />";
  19. }
  20. text += "<br />";
  21. }
  22. $("#result").html(text);
  23.  
  24. },
  25. error: function(oops) {
  26. // oops.statusText returns error
  27. $("#result").html(oops.statusText);
  28.  
  29. }
  30. });
  31.  
  32. </script>

Télécharger

Cliquez sur la vignette pour voir la requête et la réponse :

PNG - 41.6 ko

(Article à compléter. Mais est-ce pertinent ? L’utilisation de script expose le jeton, ce n’est pas la méthode recommandée).

Notes

[1La traduction française "multi-origines" est inexacte : la requête n’a évidemment qu’une seule origine, mais celle-ci est indéfinie vue du RS, et en tous cas issue d’un domaine différent du sien.

[2Voici une démonstration claire de la différence entre autorisation et authentification : le serveur de ressource va répondre sans rien savoir de l’identité de l’application cliente ni de l’utilisateur final. OpenID Connect permet de réaliser l’authentification, donc de répondre (ou non) en fonction de l’identité de l’application, de l’utilisateur final, voire des portées d’autorisation (scopes)

FAQ pour les auteur (administrateurs d’applications)

  publie le par DnC

L’Auteur est un utilisateur privilégié de OAuth Server. Il est notamment propriétaire d’une ou plusieurs applications clientes qu’il a inscrites sur le serveur à l’aide de ce site. Il est un développeur ou en possède les connaissances.

Que signifie "Il existe des informations complémentaires, connectez vous pour les voir" ?

Lorsque ce message apparait en bas d’un article, cela signifie qu’il existe des informations réservées aux utilisateurs privilégiés de ce site. Si vous avez les droits d’écriture sur la rubrique, vous serez autorisés à voir ce texte après vous être connecté.