Sécurisez l’accès à vos APIs avec OAuth2

La réponse à un nouveau besoin d’ouverture du SI

De nos jours, les Systèmes d’Information doivent être flexibles afin de répondre aux enjeux de l’économie digitale. Cette ouverture n’est cependant pas sans conséquences et la sécurisation du droit d’accès aux ressources exposées devient, plus que jamais, critique pour l’ensemble des entreprises : c’est ici qu’intervient le « protocole de délégation d’autorisation » OAuth2.

Sans OAuth2, pour donner un accès à une application tierce, il faut y stocker en clair les identifiants de l’utilisateur. Cette pratique entraîne de nombreux risques en cas de compromission, de plus il est impossible de limiter les droits de l’application de façon standardisée. Par ailleurs, identifier l’entité souhaitant accéder aux ressources s’avère compliqué, ouvrant donc la porte aux abus (i.e. Identity Spoofing) et laissant l’utilisateur et le Système d’Informations sans défense.

 

L’utilisation de OAuth2 permet de mettre en place une délégation d’autorisation pour accorder à une application tierce un accès limité sur une ressource, avec l’accord du propriétaire de celle-ci. Il n’y a alors plus besoin de stocker les identifiants de l’utilisateur dans les applications tierces.

OAuth2 : les coulisses

OAuth2 repose sur des échanges entre 4 acteurs. L’utilisateur, ici nommé Resource Owner, est capable d’accorder l’accès à la ressource pour une application nommée Client.

L’Authorization Server occupe le rôle central au sein du protocole, il est chargé d’authentifier le Resource Owner et de délivrer son autorisation sous la forme d’un jeton appelé access token. Le Resource Server quant à lui correspond au serveur où sont stockées les ressources protégées.

La confiance au cœur des échanges

Le protocole adresse des situations de sécurité différenciées en fonction de 2 types de clients :

  • Un client confidentiel est une application ou un service back-end installé dans une zone sécurisée. Ainsi, ses identifiants et tokens ne sont pas exposés au Resource Owner.
  • Un client public est généralement installé et exécuté sur la machine du Resource Owner ou exécuté par le navigateur (front-end), il est donc possible pour les personnes et les programmes ayant accès à la machine d’accéder aux identifiants et aux tokens du client.

Un client confidentiel voit son accès aux ressources protégées facilité. Cela nécessite cependant qu’il soit capable de garantir la confidentialité de ses identifiants et des tokens délivrés. Lors de leur enregistrement auprès de l’Authorization Server, tous les clients reçoivent un client id ainsi qu’un client secret pour les clients confidentiels.

De l‘autorisation à l’identification

OAuth2 offre plusieurs méthodes afin d’accéder à des ressources via la réception d’un jeton d’accès (access token).

Pour autoriser une application à accéder aux ressources, le Resource Owner doit s’authentifier auprès de l’Authorization Server.

A la différence de l’identification qui consiste à donner son identité, l’authentification prouve cette identité à travers différents moyens tels que le mot de passe, la biométrie, etc…

Token : Le sauf-conduit 2.0

L’access token est l’élément utilisé pour accéder à une ressource protégée. Accordé par le Resource Owner et délivré par l’Authorization Server, il permet d’obtenir les privilèges accordés au client (i.e. scope) et la durée de vie de cette autorisation. Il est généralement de courte durée.

Le refresh token est l’élément utilisé pour obtenir un nouvel access token, sans interaction avec l’utilisateur. Il n’est délivré qu’aux clients confidentiels. Son utilisation nécessite uniquement l’authentification du client et non plus celle du Resource Owner. Grâce au refresh token, l’utilisateur n’est pas contraint de s’authentifier régulièrement, améliorant ainsi son expérience.

Il existe 2 implémentations possibles de tokens : les tokens classiques, aussi appelés opaques, et les self-contained tokens.

  • Les tokens classiques sont des chaines de caractères inintelligibles pour l’utilisateur. Seuls les Authorization Servers sont capables de les exploiter (comprendre ici, de les associer à un scope). Ces tokens nécessitent la mise en place d’une cinématique d’échange entre l’Authorization Server, qui délivre les tokens, et le Resource Server qui les reçoit. En effet, le Resource Server est incapable de déterminer si l’access token est valable pour la requête du client.

Le Resource Server effectue un appel vers l’Authorization Server avec le token. Celui-ci retourne alors les informations représentées par ce token parmi lesquels le scope, la validité et l’identité du client à laquelle il a été délivré. Cela permet au Resource Server de valider ou non la requête du client.

  • Les tokens self-contained sont quant à eux porteurs de l’information. Ils sont généralement signés, peuvent être chiffrés et ne nécessitent pas de faire appel à l‘Authorization Server pour être validés. La signature de l’Authorization Server permet de prouver l’intégrité des tokens self-contained. En effet, en chiffrant le condensat du token avec sa clé privée, l’Authorization Server permet à n’importe quel détenteur de sa clé publique, de vérifier que le token reçu correspond bien au token envoyé et qu’il n’a pas été modifié en transit. Dans ce cas de figure, la mise en place d’une révocation de token est soumise à des contraintes, car l’Authorization Server doit être en mesure de faire part de la révocation à tous les acteurs. Dans les faits, la durée de vie des self-contained tokens est très courte pour répondre à cette contrainte.

    OpenID Connect à votre service

    Les principes fondateurs et les concepts proposés par le standard OAuth2 ont été présentés plus haut. Les échanges entre différentes applications peuvent être sécurisés via Oauth2 par l’échange de tokens délivrés et vérifiés par l’Authorization Server.

    Dans cet partie, nous introduirons OpenID Connect et présenterons les fonctionnalités apportées par OpenID Connect.

    De nouvelles fonctionnalités avec OpenID Connect

    OpenID Connect (abrévié en « OIDC » dans la suite de ce document) est une couche d’identification complémentaire au protocole OAuth 2.0. Ce protocole, à l’inverse d’OAuth2, permet aux clients de vérifier l’identité de l’utilisateur final via un ID token, ainsi que d’obtenir des informations de profil de base sur l’utilisateur final.

    En revanche, bien qu’OpenID Connect soit basé sur OAuth2, le vocabulaire concernant les acteurs des deux protocoles sont différents :

OAUTH2

  • Resource Owner : Entité (personne, machine, …) qui possède les droits sur la ressource.
  • Client : L‘application (mobile, web, …) qui veut accéder aux ressources protégées.

  • Authorization Server : Serveur qui authentifie le Client et qui lui délivre des Tokens.
  • Resource Server : Serveur contenant la ressource protégée à laquelle le Client veut accéder.

OPENID CONNECT:

  • End-User : Le Resource Owner dans OIDC est forcément une entité qui possède une identité propre. Participant humain.
  • Relying Party (RP): Client OAuth2 qui délègue l’authentification d’un End-User par un OpenID Provider.
  • OpenID Provider (OP) : Authorization Server OAuth2, capable d’authentifier un End-User et de fournir des Claims à une Relying Party.
  • Resource Server : Serveur contenant la ressource protégée à laquelle la Relying Party veut accéder

L’ID Token avec OpenID Connect

L’ID token est spécifique à OIDC. C’est un JSON Web Token (JWT) qui permet de diffuser l’identité d’un utilisateur qui s’est authentifié auprès d’un OpenID Provider. Il est délivré par l’OpenID Provider en même temps que l’access token.

Un claim est une paire « clé / valeur » qui représente une partie des informations du Ressource Owner. Ainsi, l’ID token est composé d’un ensemble de claims qui définissent le contexte d’authentification mais aussi des informations personnalisables sur l’utilisateur comme son nom, son email ou son numéro de téléphone.

Il est découpé de la façon suivante :

Header 

Il définit le type de token et l’algorithme de hashage utilisé.

Payload

Il contient des informations concernant :

  • L’identité d’un Resource Owner
  • L’Authorization Server émetteur
  • Le token (date de création, durée de validité …)
Signature

Hash du header et du payload chiffré avec la clé secrète de l’OpenID Provider.

 

L’identité du End User

Relying Party

On a vu que, pour l’identité du End User, les Relying Party peuvent se reposer sur l’ID Token. Cependant, ce token ne correspond qu’à un état des informations d’identité à l’instant de sa génération. Ainsi, si le End User change son numéro de téléphone, l’ID token sera toujours valide mais ne sera plus à jour.

Pour permettre de rafraîchir ces informations, l’OpenID Provider expose un autre service, le userinfo_endpoint. Ce service permet de récupérer les informations récentes sur le End User, ainsi que d’éventuelles informations complémentaires à l’ID Token. Ce service n’est accessible que via une requête portant un Access Token.

Pour qu’un ID Token soit valide, il doit contenir certains claims obligatoires tels que :

  • iss : Issuer Identifier, permet d’identifier le fournisseur de l’ID Token (celui qui a authentifié).
  • sub : Subject Identifier, identifiant local et unique pour le End-User au sein de l’Issuer (OpenID Provider) consommé par la Relying Party.
  • aud : Audience, à qui ce Token est destiné. Autrement dit, le « client_id »  (terme OAuth2) de la Relying Party.
  • exp : Expiration Date, le Token ne doit plus être accepté après cette date.
  • iat : Issued At, date à laquelle le Token est délivré.

Il doit être signé par l’OpenId Provider qui l’a émis, afin que les clients, qui se basent sur cet ID token pour établir l’identité de l’utilisateur, puissent vérifier :

  • Que le token est intègre
  • Qu’il a bien été émis par une organisation de confiance
  • Qu’il n’a pas été corrompu par une entité malveillante qui essayerait de se faire passer pour ce qu’elle n’est pas

Il est important de noter que l’access Token et l’ID Token ont un rôle bien différent. L’ID Token ne doit pas être utilisé pour valider l’autorisation d’accès aux APIs mais pour renseigner sur l’identité de l’utilisateur final.

OpenID Connect discovery

Bien que les Services Web exposés par les OpenID Provider soient normés, leur dénomination ne l’est pas. Ainsi, un serveur pourrait avoir comme Authorization Endpoint « /authorize » et un autre serveur avoir « /authorization ».

Pour pallier la difficulté pour les Relying Party à communiquer avec des OpenID Provider différents sans avoir à connaître la dénomination exacte de leurs services à l’avance, OpenID Connect a spécifié un service REST commun afin que les OpenID Provider puissent exposer leur configuration.

Ce endpoint est : .well-known/openid-configuration. La configuration est au format JSON et comporte, entre autres, tous les services exposés par l’OpenID Provider, ainsi que les services OAuth.

Figure 1 – Exemple de réponse du Endpoint : /.well-known/openid-configuration

L’identité du End User

Relying Party

On a vu que, pour l’identité du End User, les Relying Party peuvent se reposer sur l’ID Token. Cependant, ce token ne correspond qu’à un état des informations d’identité à l’instant de sa génération. Ainsi, si le End User change son numéro de téléphone, l’ID Token sera toujours valide mais ne sera plus à jour.

Pour permettre de rafraîchir ces informations, l’OpenID Provider expose un autre service, le userinfo_endpoint. Ce service permet de récupérer les informations récentes sur le End User, ainsi que d’éventuelles informations complémentaires à l’ID Token. Ce service n’est accessible que via une requête portant un Access Token.

Figure 2 – Exemple basique d’une réponse du userinfo_endpoint

Resource Server

Le transfert de l’identité du End User aux Resource Servers dépend de l’Architecture mise en place, de la présence ou non d’une solution d’API Management, de la politique de développement du Resource Server ou encore de la confiance existant entre les différents acteurs.

Voici quelques exemples de process rencontrés chez nos clients :

  • Transfère de l’ID Token au Resource Server en plus d’un access Token. Charge au Resource Server de valider les tokens et de les exploiter. Il dispose ainsi de l’identité du End User (ID Token) et de son périmètre d’action (access Token).
  • Les requêtes contiennent uniquement l’access Token (et pas ID Token). Charge au Resource Server de demander à l’OpenID Provider les informations dont il a besoin (userinfo Endpoint).
  • Utilisation d’une API Gateway qui se chargera de récupérer les informations auprès de l’OpenId Provider pour enrichir ensuite la requête avec des éléments d’identité pour le Resource Server.

Cet article nous a permis de présenter la surcouche OpenID Connect qui permet d’adresser les aspects inhérents à l’authentification et l’identification des End User.

Dans le prochain article, nous verrons comment ces protocoles s’utilisent et dans quels cas d’usage.

Auteur : Tahar Sayagh

Cloud Architect - DevOps Engineer

Auteur : Ahmad TOHAMI

Architecte IT

Auteur : Timothé Mailhac

Consultant en Architecture des Systèmes d'Information