OAuth2 Family

Est-il encore nécessaire de devoir sensibiliser aux enjeux de la sécurité des systèmes d’informations ? Non, pourtant l’actualité parle d'elle-même et aujourd’hui, nous pouvons constater que les faits d’armes des hackers au fil de ces dernières années n'ont cessé d’augmenter ! Qu’il s'agisse de fuites de données comme chez Deezer ou de demandes de rançons à l'encontre de centres hospitaliers comme celui de Versailles, la situation actuelle montre bien que la construction de systèmes résilients aux intrusions est un enjeu majeur.

Heureusement, nous ne sommes pas sans solutions ni leviers pour répondre à ces problématiques. En termes de stratégie de défense, par exemple, il est conseillé de réduire systématiquement la surface d’attaque offerte aux éventuels hackers. Il est également conseillé de mettre en place des contre-mesures multiples et variées à chaque niveau du périmètre du système afin de tendre vers le très connu modèle en gruyère. Son utilisation, pragmatique, permettra alors de limiter la profondeur d’intrusion (illustré par le schéma ci-contre présentant de manière non exhaustive quelques outils et pratiques).

Ici, nous allons nous intéresser à la gestion des autorisations et des identités au travers du protocole Oauth2. Nous passerons en revue son cas d’usage ainsi quelques-unes de ses spécificités (qui pourront être approfondies grâce aux articles ici et ici). Puis, nous présenterons les extensions de ce protocole en traitant de manière large OpenID Connect, UMA et CIBA dont nous identifierons les cadres d’emploi ainsi que quelques-uns de leurs aspects techniques.

OAuth2

OAuth2 est un protocole d’autorisation paru en 2012 issu de OAuth et implémentant la RFC 6749. Il permet, via une délégation de la gestion des autorisations, la sécurisation de la consommation d’API entre applications.

Cas d’usage

Historiquement, avec l'essor des services en ligne, il est très vite devenu nécessaire à ces services de communiquer et de partager des données afin de fournir une expérience utilisateur plus riche.

En première approche, il est toujours possible de mettre en place une configuration spécifique pour chaque service. Cette configuration aura alors pour responsabilité de gérer les accès spécifiques aux autres services sous l'étiquette de l'utilisateur lui-même. Pragmatique, cette approche montre cependant rapidement ses limites en termes de gestion.

En effet, l’utilisateur va se retrouver à la fois devant une tâche très laborieuse de gestion décentralisée de ses mots de passe, mais aussi de sécurité par la dissémination de ceux-ci auprès d’opérateurs en qui la confiance est faible.

Le protocole

Plutôt que de leur faire partager des informations sensibles, OAuth2 propose de faire porter cette responsabilité de gestion des droits et autorisations d'accès à un composant tiers, le serveur d'autorisation consolidant le détail des droits nécessaires à la consommation des services et en qui la confiance pourra être bien plus élevée.

Le principe est simple : le client (ici le service consommateur) va capturer auprès du propriétaire de la ressource (l’utilisateur) les informations (un code obtenu à la suite d’une redirection de l’utilisateur sur le serveur d'autorisation pour que celui-ci s’authentifie) lui permettant de demander au serveur d'autorisation les droits qui lui permettront d’accéder à la ressource. Ces droits se matérialisent dans un payload JSON sous la forme d’un access_token, de type Bearer (opaque ici, mais possiblement encodé sous la forme d’un JWT) évitant à l’utilisateur de diffuser ses mots de passes :

{
    "access_token": "ya29.a0AfH6SMA0iZI6b0K05BBcrWjfKyVF0kZYLS8fbt9O9Ighx12VokTEdeDC3a99gK8ApamgaZ0oGQRyA8V3Iud6q1LmC3TdT1VzM9_PkO7kUw7cF9FrQ3ERHDYmkiDvLIqgT5dl6FtTNa5ZYvD2C6EVGAPX-BuA",
    "expires_in": 3599,
    "refresh_token": "1//03huLouzKkgonCgYIARAAGAMSNwF-L9Ir8ZkymT7C_rqjOaxpip6EykonnIkk0eJq-rhLF25JBRq0nYvBx5vxN_mlkOCeyI30MxU",
    "scope": "https://www.googleapis.com/auth/youtube.readonly",
    "token_type": "Bearer"
}

À noter que le serveur d’autorisation ne donne pas directement les accès, car le mécanisme OAuth2 prévoit justement que la validation de ce jeton ne peut être réalisée que par le serveur de ressources (par ses propres moyens, celui-ci pouvant s’appuyer éventuellement sur serveur d'autorisation lorsque le client cherchera à consommer la ressource ;  ceci est formalisé par une RFC spécifique, la RFC 7662, concernant un potentiel endpoint d’introspection porté par le serveur d'autorisation).

Le refresh token peut être optionnel. Il permet au client de renouveler son access token auprès du serveur d’autorisation sans devoir rejouer à nouveau tout le processus d'acquisition des autorisations.

Différents modes d’acquisition des droits (authorization grant) sont possibles pour obtenir un access token :

  • L’autorisation par code, le cas nominal
  • L’autorisation pour device (télévision, …)
  • L’autorisation implicite, cas où le client est local à l’utilisateur (dans un navigateur web, cas d’une application monopage, SPA, par exemple), non conseillé à l’utilisation.
  • L’autorisation par mot de passe, cas où le serveur d’autorisation et le client sont issus de la même entité organisationnelle (et pour laquelle la confiance est absolue ; un couple Keycloak Apache Httpd par exemple)
  • l’autorisation par les identifiants Client, cas où la ressource appartient au client correspondant généralement à une intégration machine-to-machine.

À noter que dans la version draft de OAuth2.1, seules sont reconduites l'autorisation par code, par refresh token et par les identifiants Client, mais cette nouvelle version propose un moyen d’extension pour en définir de nouveaux types.

Déclinaisons

OAuth2 permet la gestion des autorisations par un processus d'échange entre systèmes permettant de garantir plus de sécurité et de confiance. Nous allons voir que ce n’est pas tout, car si ce use case peut paraître plutôt limité au premier abord, nous allons voir que d’autres vont pouvoir être déclinés sur cette base et ainsi fournir plus de richesse :

  • d’authentification avec OpenID Connect
  • de partage des ressources avec UMA
  • de déport d’authentification avec CIBA [ciba-core]

OpenIdConnect

Cas d’usage

OAuth2 ne gère que l’autorisation d'accès et cela ne permet pas de savoir si l'accès à une information est réalisé au nom d’un individu en particulier, ce qui, dans certains cas, peut avoir une valeur importante pour le client (l'accès à un dossier médical par exemple, il importe que même si un utilisateur en a le droit, nous puissions savoir s’il avait le besoin d’en connaître ! Il faut donc être en mesure de l’identifier)

OpenId Connect se charge de remplir ce rôle en restant conforme au processus que nous avons vu précédemment pour OAuth2.

Implémentation

Dans la pratique, pour assurer l’authentification, OpenId Connect va enrichir le payload OAuth2 précédemment décrit avec un token ID matérialisé par un nouveau champ, l’id_token, un JWT encodé en base64. La particularité de ce JWT est d'être signé permettant de garantir l’authenticité des informations qu’il contient.

Par exemple, cet id_token:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTA3MDc5NjQ2OTY2NCIsImVtYWlsIjoiY29sbG9udmlsbGUudGhvbWFzQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhdF9oYXNoIjoiUU9sNnRvTFdRIiwiaWF0IjoxNjUzOTI1NzY5LCJleHAiOjE2NTM5MjkzNjl9.D9T47VXg69hHuNL_XH5ggS2dC-AnMEVBY8wmQCdsWWWLN2W28DnCebt2ZeT-LkdHmrbXSiXB3LNNzdAyfPxLqfHPJMeFhJU1fZaaRVuJcG0_3-yO5JvA-7NaU2tzCVKWN5dueTDex40eo3NIW5Vf0N7LVy-IYg89V2cvssz6R7E

peut être décodé (sur le site jwt.io) et nous donner les informations suivantes

nous permettant d’identifier clairement l’identité de l’utilisateur pour lequel une demande d'autorisation d'accès est réalisée.

UMA

Cas d’usage

Via Oauth2 et OpenId Connect, nous remplissons le cas d’usage de l’identification et de la délégation des autorisations pour la consommation de ressources appartenant à l'utilisateur. Ces fonctionnalités partent du postulat que ces ressources appartiennent à l‘utilisateur. Mais qu’en est-il si un autre utilisateur souhaite accéder à des ressources ne lui appartenant pas ? En substance également, comment faire pour que le détenteur de cette ressource puisse donner à un autre utilisateur le droit d’y accéder ?

UMA (User Managed Access) va répondre à cette problématique de partage de ressource en proposant toujours sur la base du processus OAuth2 de nouveaux moyens d'échanges d’informations facilitant pour un utilisateur l’attribution dynamique de droits spécifiques à des consommateurs.

UMA, en apportant ces fonctionnalités, va donner au Resource Owner la capacité de gérer et contrôler dynamiquement les accès par des tiers (Requesting Party) à ses ressources, permettant ainsi la mise en place de services de partage entre utilisateurs.

Par exemple, si Bob dispose d’une ressource telle qu’un fichier ou une image dans le serveur de ressource, celui-ci, grâce à UMA, va être capable de donner à Alice des droits pour que sur la base de son identité celle-ci puisse la consommer.

Par rapport à OAuth2, la configuration des échanges est très similaire du point de vue du consommateur (le Requesting Party). La différence notable est que cet utilisateur n’est plus le Resources Owner; ce dernier ayant désormais une nouvelle responsabilité de définir et configurer des permissions qui devront être vérifiées lors du processus d’accès aux données.

Implémentation

Le protocole UMA se décline dans un processus en quatres étapes :

  1. Enregistrement de la ressource et gestion des permissions
  2. Forge d’un ticket de permission suite à une demande d'accès à une ressource (Permission endpoint) par le client
  3. Acquisition des permissions par le Requesting Party matérialisé sous la forme du RPT (Requesting Party Token)
  4. Vérification de la légitimité du token d'accès (le Requesting Party Token, RPT) par le serveur de ressource auprès du serveur d’autorisation

Ces différentes étapes sont décrites plus précisément dans deux spécifications, UMA Federated couvrant la problématique technique des interactions du serveur de ressource et du serveur d’autorisation et UMA Grant couvrant le processus d'accès à la ressource par le client :

  • UMA Federated traite de la gestion des interactions entre le serveur de ressources et le serveur d’authentification en détaillant :
  • L’enregistrement d’une ressource et la gestion de ses permissions (Resource Registration)
  • La forge d’un ticket de permission suite à une demande d'accès à une ressource (Permission endpoint) par le client qui permettra de déterminer les droits d'accès à la ressource partagée dans la phase d’authentification (phase 4) réalisée par le Requesting Party.
  • La vérification de la légitimité du token d'accès (le Requesting Party Token, RPT) par le serveur de ressource auprès du serveur d’autorisation (Introspection Endpoint)
  • UMA Grant traite du processus d’acquisition des permissions par le Requesting Party (ce processus, Core flow, se positionne entre les processus Permission endpoint et Introspection Endpoint vus ci-dessus). Avec le ticket de permission (et son propre bearer de connexion), l’utilisateur va acquérir le RPT auprès du serveur d'autorisation, consolidant à la fois les autorisations et l’authentification de l’utilisateur ainsi que ses permissions effectives sur la ressource.

UMA n’est pas un protocole simple, mais en se basant sur OAuth2 et par l’ajout de ces différentes fonctionnalités, les utilisateurs ont un contrôle direct sur l'accès à leurs données leur permettant de décider qui peut y accéder, dans quel contexte et limites.

CIBA

Cas d’usage

Au-delà de ces différents use cases couvrant la gestion des autorisations, l'authentification et le partage de ressources, nous pouvons constater que l'ensemble de ces processus est conditionné par un mode d'authentification quasi unique fourni par le serveur d'autorisation et d'authentification qui va permettre l'obtention de l'access token.

Cette limitation peut être dépassée à l'aide du protocole CIBA (Client Initiated Backchannel Authentication explicité ici par l'un de ses implementeurs) qui propose, via l'adjonction d'un périphérique (un smartphone personnel, par exemple), d'étendre le processus d'authentification. L'intérêt de ce périphérique est multiple :

  • Il permet une authentification plus sécurisée des utilisateurs en utilisant des facteurs d'authentification plus sécurisés tels que la biométrie ou les jetons d'accès à usage unique
  • Il facilite et simplifie l'authentification, améliorant ainsi l'expérience utilisateur
  • Il augmente la confiance que l'on peut avoir dans le processus d'authentification en limitant les possibilités d'attaque, par exemple lorsque le navigateur est utilisé sur un terminal qui n'est pas de confiance (utilisation dans un cybercafé, par exemple, ou sur un ordinateur de prêt).

Avec CIBA, nous clôturons donc cet article en répondant à ce dernier use case dans une variation de l'utilisation de OpenID Connect.

Implémentation

On identifie bien ici que par l'intégration d’une nouvelle interaction utilisateur, le processus va devoir être capable de gérer une forme d’asynchronisme pendant l’attente de l’action utilisateur sur l’authentification device. Pour ce faire, CIBA propose 3 modes de fonctionnement entre le Client et l'Autorisation Server :

  • pool mode: après avoir initié le processus CIBA et reçu sa prise en compte par l'autorisation server, le client va venir pooler celui-ci pendant que l'autorisation server sollicite l’authentification device pour obtenir l'autorisation utilisateur.
  • ping mode: après avoir initié le processus CIBA et reçu sa prise en compte par l'autorisation server, le client va attendre un ping de celui-ci afin d'opérer le processus d’acquisition du token.
  • push mode: après avoir initié le processus CIBA et reçu sa prise en compte par l'autorisation server, le client va se mettre en attente active du token directement.

On notera que dans la spécification de CIBA, l'Authorization Server porte la responsabilité de l’interaction avec l’Authentification Device ce qui peut en termes d’architecture être problématique. On trouvera donc naturellement dans les implémentations actuelles (comme celle de keycloak) l’introduction d’un composant intermédiaire le Decoupled Auth Server dont le rôle est de supporter l'implémentation technique de l’interaction avec l’Authentification Device.

Conclusions

Dans le processus d'authentification et d'autorisation, OAuth2, OpenID Connect, UMA et CIBA sont des protocoles clés.

Au-delà d'être la base de l’ensemble de ces standards, OAuth2 est un socle permettant, pour les utilisateurs, la sécurisation et la gestion de l'accès à des ressources partagées entre différents services.

OpenID Connect fournit de son côté une couche supplémentaire au-dessus de OAuth2, permettant une authentification forte et une interaction utilisateur plus riche qui peut être complétée par UMA pour une meilleure gestion du partage de ressources entre les utilisateurs eux-mêmes.

Enfin, CIBA fournit une méthode d'authentification asynchrone et déportée, ce qui permet une interaction utilisateur plus fluide et offre une sécurité accrue selon les conditions d'accès aux ressources.

Dans l'ensemble, ces protocoles, qui se retrouvent dans des services SasS tel que Okta ou On Premise comme Keycloak, offrent des avantages importants pour l’utilisateur en termes de fiabilité, de confiance et de répartition des responsabilités car leur standardisation et leur interopérabilité avec les différents fournisseurs d'identité et applications fournissent à ceux ci une expérience plus homogène et surtout plus sécurisée.