Le protocole OAuth2.0
Et comment l’expliquer à votre boss.
Le protocole OAuth2 est un standard qui permet à une application cliente de pouvoir accéder de façon limitée aux ressources d’un autre application cliente.
Reprenons notre exemple avec Emma (article sur l’Identité numérique) qui souhaite récupérer ces contacts Gmail sur son réseau professionnel LinkedIn pour pouvoir les ajouter.
L’utilisatrice : Emma, va se connecter à l’application LinkedIn qui va lui proposer de synchroniser ces contacts Gmail afin de les ajouter à son réseau professionnel.
Quand l’utilisatrice va cliquer sur le bouton qui lui propose de récupérer ses contacts Gmail. Elle va être redirigée vers l’interface de connexion de son compte Google.
Après s’être authentifiée. Emma va ensuite devoir autoriser LinkedIn a accéder à ses contacts. Notons que dans le process d’identification, LinkedIn ne s’est pas du tout occupé de l’authentification de l’utilisateur. Cela va être géré par l’intermédiaire du protocole Open ID connect qui va apporter une sur-couche à OAuth2. En ajoutant la notion d’identité que nous allons voir dans un prochain article.
Le mot de passe d’Emma n’est jamais communiqué entre les deux API(LinkedIn et Google). Il s’agit de déléguer l’authentification à un tiers qui va s’occuper de vérifier si l’utilisateur existe bien dans sa base de données. L’Authorization Server va ensuite donner un code d’autorisation au Client App qui va permettre de poursuivre le processus pour récupérer les contacts de l’utilisateur.
Le système d’autorisation du protocole OAuth2 se base sur 4 rôles pour faire marcher tout son système d’autorisation.
Le propriétaire de la ressouce : Ressource owner. Celui à l’origine de la demande (l’utilisateur final), dans notre cas Emma.
Le client : Client Application. C’est l’application ou le service qui va aller demander l’autorisation pour accéder une partie des ressources. Ici, LinkedIn.
Il faut savoir qu’il existe deux types de Client Application :
- Le client classique ou client confidentiel est une application qui va pouvoir s’authentifier de manière sécurisée auprès de l’Authorization Server.
- Le client public, qui comme son nom l’indique va exposer certaines informations au sein du navigateur.
Le serveur de ressource : Ressource Server. Le serveur qui héberge la ressource protégée. C’est lui qui va accepter ou non, de partager une ressource.
Le serveur d’autorisation : Authorization Server. Le serveur qui va fournir les access tokens aux clients. Un access token est un jeton qui va permette à son possesseur d’avoir le droit d’accéder à une ressource. Après la confirmation de l’authentification par l’utilisateur (Emma). Le serveur va ensuite donner une autorisation au Client Application d’avoir accès aux contacts Gmail de l’utilisateur.
Si nous reprenons notre exemple, Emma va autoriser une fois l’application pour récupérer ses contacts Gmail. C’est LinkedIn qui va prendre en charge la communication avec l’API externe Google, via OAuth2.
Avant de pouvoir effectuer ces échanges. LinkedIn va devoir s’enregistrer comme service (création d’un client OAuth) auprès de l’Authorization Server (Google API).
LinkedIn doit fournir des informations d’enregistrements, comme le nom de son site, l’URL de callback et le scope de la demande d’autorisation avant de pouvoir faire toute demande. Cet enregistrement ce fait au moment où LinkedIn va intégrer le bouton de synchronisation des contacts Gmail, selon les règles définies par l’API Google.
Une fois ces infos renseignées, le service va pouvoir créer un client OAuth sur la plateforme Google. Google va lui donner un ID Client(client_id) et un Secret Client (client_secret).
Le client_id est un identifiant unique qui doit être utilisé pour communiquer auprès de Google. Tandis que le client_secret comme son nom l’indique doit rester secret. Elle est stockée côté serveur et va permettre au Client App de s’authentifier auprès de l’Authorization Serveur. Lors de la demande d’un access token, le Client App va générer un JWT Bearer Authorization Grant et va le signer avec sa clé privée.
Une fois que le service LinkedIn est bien enregistré comme client OAuth auprès de Google. LinkedIn va pouvoir lancer la demande d’autorisation auprès de l’utilisateur. Pour lui demander s’il autorise le Client App LinkedIn à avoir accès en lecture à ses contacts Gmail. LinkedIn va alors utiliser le type d’autorisation avec code (Authorization Code).
Il faut savoir qu’il existe autant de types d’autorisation (Grants types) que de façons de se connecter à un Authorization server. Il existe un type adéquat selon le scénario que vous avez besoins. Les différents types vont offrir des garanties de sécurités différentes.
Le type le plus utilisé est celui que l’on vient de voir : l’Authorization Code. C’est aussi le type le plus sécurisé. L’autorisation repose sur l’interaction avec un utilisateur sur un navigateur. Il ne peut alors être utilisé par une machine, ou pour communiquer d’API à une autre API.
La demande va prendre cette forme :
https://accounts.google.com/o/oauth2/v2/auth?client_id=CLIENT_ID&response_type=CODE&scope=contacts.readonly&redirect_uri=CALLBACK_URL&access_type=offline
- Le endpoint de l’API qui va permettre de gérer les autorisations. (https://accounts.google.com/o/oauth2/v2/auth)
- On a ensuite le fameux client_id qui va permettre d’identifier l’application.
- La response_type, ici on va spécifier que l’application souhaite obtenir un Authorization Code.
- Le scope, qui permet de spécifier le niveau d’accès que l’on souhaite avoir : ici on souhaite lire les contacts.
- Le redirect_uri qui est l’URL de redirection où le service va ensuite rediriger l’utilisateur après avoir généré un code d’autorisation.
- Pour Google on a besoin d’un accès offline, qui va permettre de communiquer avec l’API de Google sans que l’utilisateur soit présent sur le navigateur. L’accès offline permet au Client App d’obtenir un refresh token, notion que nous allons voir un peu plus bas dans l’article.
Une fois qu’Emma a autorisé le Client App (LinkedIn). Celui-ci va récupérer un code (Authorization Code), et va alors l’échanger contre un access token. Un peu plus haut, nous avons vu la notion de client_secret et client_id. Le Client App va utiliser le client_secret pour s’authentifier auprès de l’Authorization server pour demander un access token.
Pour rappel l’access token est comme un ‘valet key’. Une clé de voiture que l’on peut passer à un voiturier afin de garer sa voiture sur un parking, sans que le voiturier puisse accéder à toutes les fonctionnalités de la voiture.
L’access token va permettre à notre application (LinkedIn), d’aller faire une demande au nom de l’utilisateur (Emma) à l’API de Google pour pouvoir récupérer ces contacts. Ainsi, il permet de demander l’accès à une ressource protégée qui est accordée par le Ressource owner et délivrée par l’Authorization server.
L’access token possède souvent une durée de vie très limitée dans le temps. Il ne possède pas de format particulier. La plupart du temps, c’est une chaîne de caractère. L’application n’a pas besoin de savoir ce qui est présent dans l’access token. Il va récupérer le jeton et l’envoyer via une connexion sécurisée (HTTPS) au Ressource Server qui va devoir valider la demande d’acces à la ressource ou la refuser.
La réponse à la demande d’access token donnée par le Ressource Server va prendre cette forme :
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
- On va avoir obligatoirement un access_token. (chaîne de caractères émise par l’Authorization server)
- On a obligatoirement le token_type (Bearer).
- La durée de l’access token : expires_in qui est recommandée, mais non obligatoire.
- Le refresh_token qui lui aussi est facultatif. Au moment où la durée de validation de l’acces token est dépassé, le refresh token permet au Client App de demander un autre access token valide sans passer par l’utilisateur. Ceci permet au passage d’améliorer l’expérience utilisateur.
- On peut ajouter d’autres paramètre comme le scope. Quand le scope ne change pas par rapport à l’Authorization Code, ce champ est optionnel. Par contre, si le scope est différent il faut l’ajouter. (Dans le cas où Emma, modifierait les autorisations qu’elle donne à LinkedIn pour accéder à ces informations google)
Il est possible que la demande échoue. Pour plusieurs raisons comme un code d’autorisation non valide ou bien l’URL de redirection qui n’est pas connue par l’Authorization Server.
L’Authorization Server va nous renvoyer une 400 (Bad Request). Avec un de ces paramètres d’erreur qui peuvent être :
Il est possible d’avoir deux clés supplémentaires pour aider les développeurs à comprendre le problème :
- error_description (qui ne peut contenir que des caractères ASCII, une phrase ou deux grands max)
- error_uri
Maintenant que nous avons un access token, le fameux “valet key” dont on a parlé dans l’introduction sur l’identité numérique. Nous sommes enfin autorisés à faire notre demande au Ressource Server pour obtenir les contacts Gmail d’Emma et les afficher sur l’application LinkedIn.🎉
Imaginons qu'Emma n’ait pas eu le temps d’ajouter ces contacts Gmail à son application LinkedIn. Elle revient plus tard et souhaite finaliser le processus. L’access token étant limité dans le temps, il n’est plus valide. Le Client App (LinkedIn) n’a pas besoin de refaire toutes les étapes. Il peut utiliser le type d’autorisation Refresh Token. Il va échanger son refresh token contre un access token. Ce type permet au Client App de disposer d’un access token valide sans aucune intervention de l’utilisateur.
Le Client App va alors rappeler l’Authorization Server pour demander un nouvel access token.
https://accounts.google.com/o/oauth2/token?client_id=CLIENT_ID&client_secret=SECRET_ID&grant_type=refresh_token&refresh_token=YOU_REFRESH_TOKEN
Nous allons ensuite recevoir un nouvel accès token avec une nouvelle date d’expiration. Afin de pouvoir récupérer nos contacts Gmail pour les afficher dans notre application.
Allez plus loin :
- Sécuriser OAuth2 avec l’aide du type PKCE pour les applications SPA et mobiles (à venir)
- Ajouter une couche d’identité à OAuth2 avec le protocole OIDC
Sources :