Comprendre OAuth 2.0 et ses Flux
Introduction : L'Autorisation Déléguée au Cœur des Applications Modernes
Dans l'écosystème du développement web moderne, la gestion de l'authentification (vérifier l'identité de l'utilisateur) et de l'autorisation (définir ce que l'utilisateur est autorisé à faire) est primordiale. Cependant, donner à une application tierce l'accès à nos données sans compromettre la sécurité est un défi. Imaginez que vous souhaitiez qu'une application de retouche photo accède à vos images stockées sur Google Photos, ou qu'une application de gestion de tâches puisse lire votre calendrier Google. Comment permettre cela sans donner votre mot de passe Google à chaque application ? C'est précisément le problème qu'OAuth 2.0 résout.
OAuth 2.0 est un protocole d'autorisation qui permet à une application (le "client") d'obtenir un accès limité aux ressources d'un utilisateur sur un autre service (le "serveur de ressources"), sans que l'utilisateur n'ait à partager ses identifiants. C'est une méthode de délégation sécurisée d'accès.
Ce que n'est PAS OAuth 2.0 :
- Ce n'est PAS un protocole d'authentification. OAuth 2.0 ne vous dit pas qui est l'utilisateur, mais plutôt si l'utilisateur a autorisé une application à faire quelque chose en son nom. Pour l'authentification, on utilise souvent OpenID Connect, qui est une couche construite sur OAuth 2.0.
- Ce n'est PAS un système de gestion d'utilisateurs. Il ne stocke pas de noms d'utilisateur ou de mots de passe.
Concepts Fondamentaux d'OAuth 2.0 : Les Acteurs Clés
Pour comprendre OAuth 2.0, il est essentiel de connaître les rôles et termes spécifiques :
-
Propriétaire des Ressources (Resource Owner) : C'est l'utilisateur final qui possède les données ou ressources protégées (ex: vos photos sur Google Photos, vos emails sur Gmail). C'est lui qui donne son consentement pour l'accès.
-
Client (Client) : L'application tierce qui souhaite accéder aux ressources du propriétaire des ressources (ex: l'application de retouche photo, l'application de gestion de tâches). Le client peut être une application web, mobile, desktop, etc.
- Client Confidentiel : Une application capable de garder un secret (ex: une application web côté serveur). Elle peut stocker un
client_secreten toute sécurité. - Client Public : Une application incapable de garder un secret (ex: une application SPA JavaScript exécutée dans un navigateur, une application mobile).
- Client Confidentiel : Une application capable de garder un secret (ex: une application web côté serveur). Elle peut stocker un
-
Serveur d'Autorisation (Authorization Server) : Le serveur qui interagit avec le propriétaire des ressources pour obtenir son autorisation et délivre les jetons d'accès au client. Il gère le processus d'autorisation.
-
Serveur de Ressources (Resource Server) : Le serveur qui héberge les ressources protégées de l'utilisateur (ex: l'API Google Photos, l'API Gmail). Il accepte les jetons d'accès et sert les ressources demandées.
-
Portées (Scopes) : Des chaînes de caractères qui définissent les permissions spécifiques que le client demande (ex:
read_photos,write_calendar). L'utilisateur voit ces scopes et les approuve ou les rejette. -
URI de Redirection (Redirect URI / Callback URL) : L'URL à laquelle le serveur d'autorisation renvoie le propriétaire des ressources (avec un code d'autorisation ou un jeton d'accès) après qu'il a donné son consentement. Cette URL doit être pré-enregistrée auprès du serveur d'autorisation.
-
Code d'Autorisation (Authorization Code) : Un code temporaire et à usage unique que le serveur d'autorisation fournit au client. Ce code est ensuite échangé contre un jeton d'accès.
-
Jeton d'Accès (Access Token) : La "clé" que le client utilise pour accéder aux ressources protégées du serveur de ressources. Il est généralement de courte durée et doit être inclus dans l'en-tête
Authorizationdes requêtes HTTP. -
Jeton de Rafraîchissement (Refresh Token) : Un jeton de longue durée qui peut être utilisé par le client (généralement confidentiel) pour obtenir un nouveau jeton d'accès lorsque l'ancien expire, sans avoir à redemander l'autorisation à l'utilisateur.
Le Fonctionnement Général d'OAuth 2.0 (Vue d'Ensemble)
Le flux OAuth 2.0 suit généralement ces étapes :
- Le client demande l'autorisation : L'utilisateur clique sur "Se connecter avec Google" ou "Accorder l'accès" dans l'application cliente.
- Redirection vers le Serveur d'Autorisation : Le client redirige le navigateur de l'utilisateur vers le serveur d'autorisation, en incluant des paramètres comme l'ID du client, les scopes demandés et l'URI de redirection.
- Consentement de l'Utilisateur : Le serveur d'autorisation authentifie l'utilisateur (s'il ne l'est pas déjà) et lui demande de donner ou de refuser son consentement pour que le client accède aux ressources demandées (en fonction des scopes).
- Réponse du Serveur d'Autorisation : Si l'utilisateur donne son consentement, le serveur d'autorisation redirige le navigateur de l'utilisateur vers l'URI de redirection du client, en y joignant un code d'autorisation (ou, dans certains flux, directement un jeton d'accès).
- Échange du Code contre un Jeton d'Accès (pour certains flux) : Le client (côté serveur) reçoit le code d'autorisation et l'échange directement avec le serveur d'autorisation (via une requête sécurisée de serveur à serveur) contre un jeton d'accès (et potentiellement un jeton de rafraîchissement).
- Accès aux Ressources : Le client utilise le jeton d'accès pour faire des requêtes aux API du serveur de ressources, en incluant le jeton dans l'en-tête
Authorization(généralement sous la formeBearer <access_token>).
Les Flux OAuth 2.0 (Grant Types)
OAuth 2.0 définit plusieurs "types d'octroi" (Grant Types), chacun adapté à des scénarios d'utilisation différents en fonction du type de client et des exigences de sécurité.
1. Flux de Code d'Autorisation (Authorization Code Flow)
C'est le flux le plus recommandé et le plus sécurisé pour les applications web côté serveur (confidential clients). Il est également utilisé pour les applications mobiles et SPAs avec l'extension PKCE.
Fonctionnement :
- Le client redirige le navigateur de l'utilisateur vers le serveur d'autorisation.
- L'utilisateur s'authentifie et donne son consentement.
- Le serveur d'autorisation redirige l'utilisateur vers le
redirect_uridu client avec unauthorization_code. - Le client (côté serveur) reçoit ce
authorization_code. - Le client effectue une requête directement au serveur d'autorisation (server-to-server) pour échanger le
authorization_codecontre unaccess_token(et unrefresh_token), en incluant également sonclient_idetclient_secret. - Le serveur d'autorisation valide le
authorization_codeet leclient_secretet renvoie les jetons. - Le client utilise l'
access_tokenpour faire des requêtes au serveur de ressources.
Avantages :
- Sécurité maximale : Le jeton d'accès n'est jamais exposé dans le navigateur de l'utilisateur. L'échange
authorization_codecontreaccess_tokense fait via une connexion directe et sécurisée de serveur à serveur, protégeant ainsi leclient_secret. - Supporte les
refresh_tokenpour un accès continu sans ré-authentification de l'utilisateur.
Quand l'utiliser : Applications web traditionnelles (avec backend), applications mobiles et Single Page Applications (SPAs) en combinaison avec PKCE.
Exemple de Requêtes (Conceptualisation des étapes) :
-
Requête d'autorisation initiale (via le navigateur de l'utilisateur) : Le client construit une URL et y redirige l'utilisateur.
<!-- Côté client (HTML ou JavaScript) --> <a href="https://auth.example.com/oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=https://your-app.com/callback& scope=read_profile%20read_photos& state=RANDOM_STATE_STRING" > Se connecter avec Mon Service </a>response_type=code: Indique que l'on attend un code d'autorisation.client_id: L'identifiant de votre application.redirect_uri: L'URL où le serveur d'autorisation renverra l'utilisateur.scope: Les permissions demandées.state: Une chaîne aléatoire pour prévenir les attaques CSRF.
-
Échange du code contre les jetons (requête server-to-server) : Après que l'utilisateur a donné son consentement, le serveur d'autorisation redirige vers
https://your-app.com/callback?code=YOUR_AUTH_CODE&state=RANDOM_STATE_STRING. Votre serveur backend intercepte cette requête et fait une nouvelle requête au serveur d'autorisation.# Requête cURL depuis votre serveur backend curl -X POST https://auth.example.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code&" \ -d "code=YOUR_AUTH_CODE&" \ -d "redirect_uri=https://your-app.com/callback&" \ -d "client_id=YOUR_CLIENT_ID&" \ -d "client_secret=YOUR_CLIENT_SECRET"grant_type=authorization_code: Spécifie le type d'octroi.code: Le code d'autorisation reçu.redirect_uri: Doit correspondre à celle de la première étape.client_idetclient_secret: Utilisés pour authentifier votre application.
La réponse du serveur d'autorisation ressemblera à :
{ "access_token": "YOUR_ACCESS_TOKEN", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "YOUR_REFRESH_TOKEN", "scope": "read_profile read_photos" }
2. Flux Implicite (Implicit Flow)
Ce flux était précédemment utilisé pour les applications web côté client (SPAs) et les applications mobiles (public clients), mais il est désormais considéré comme moins sécurisé et déprécié au profit du flux de code d'autorisation avec PKCE.
Fonctionnement :
- Le client redirige le navigateur de l'utilisateur vers le serveur d'autorisation.
- L'utilisateur s'authentifie et donne son consentement.
- Le serveur d'autorisation redirige l'utilisateur vers le
redirect_uridu client avec l'access_tokendirectement dans le fragment de l'URL (#access_token=...). - Le JavaScript côté client extrait l'
access_tokendu fragment de l'URL.
Inconvénients (pourquoi déprécié) :
- L'
access_tokenest exposé dans l'URL du navigateur, ce qui le rend vulnérable aux fuites via les logs du navigateur, les historiques ou les serveurs intermédiaires. - Ne prend pas en charge les
refresh_token, obligeant l'utilisateur à se ré-authentifier une fois l'accès expiré. - Aucune authentification du client (
client_secretn'est pas utilisé), ce qui rend le client moins "sûr".
Quand l'utiliser : À éviter. Toujours préférer le flux de code d'autorisation avec PKCE pour les clients publics.
3. Flux d'Identifiants du Client (Client Credentials Flow)
Ce flux est conçu pour les interactions de machine à machine, où le client est lui-même le propriétaire des ressources ou agit en son propre nom (par exemple, un service backend appelant une API externe). Il n'y a pas d'utilisateur final impliqué.
Fonctionnement :
- Le client envoie directement son
client_idet sonclient_secretau serveur d'autorisation (endpoint de jeton). - Le serveur d'autorisation valide les informations d'identification du client.
- Le serveur d'autorisation renvoie un
access_tokenau client. - Le client utilise cet
access_tokenpour accéder aux ressources protégées du serveur de ressources.
Avantages :
- Simple et direct pour les communications de service à service.
- Pas d'interaction utilisateur requise.
Quand l'utiliser : Lorsque votre application (un service backend, un script, un microservice) a besoin d'accéder à une API en son propre nom, sans qu'un utilisateur final ne soit impliqué (par exemple, un service de traitement de données qui interroge une API externe).
Exemple de Requête :
# Requête cURL depuis votre service backend
curl -X POST https://auth.example.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&" \
-d "client_id=YOUR_CLIENT_ID&" \
-d "client_secret=YOUR_CLIENT_SECRET&" \
-d "scope=read_analytics" # Scopes spécifiques aux permissions du client
La réponse du serveur d'autorisation est similaire à celle du flux de code d'autorisation, mais sans refresh_token (car il n'y a pas d'utilisateur à "rafraîchir").
4. Flux des Informations d'Identifiant du Propriétaire des Ressources (Resource Owner Password Credentials Flow)
Ce flux permet au client de demander directement les identifiants de l'utilisateur (nom d'utilisateur et mot de passe) et de les envoyer au serveur d'autorisation pour obtenir un jeton d'accès.
Fonctionnement :
- L'utilisateur entre son nom d'utilisateur et son mot de passe dans l'interface du client.
- Le client envoie ces identifiants (avec son
client_idetclient_secret) au serveur d'autorisation. - Le serveur d'autorisation authentifie l'utilisateur et renvoie un
access_token(et potentiellement unrefresh_token) au client.
Inconvénients (fortement déconseillé) :
- Risque de sécurité majeur : Le client doit gérer et transmettre les identifiants de l'utilisateur, ce qui est une violation directe du principe de "ne jamais demander le mot de passe de l'utilisateur à une application tierce". Si le client est compromis, les identifiants de l'utilisateur le sont aussi.
- Va à l'encontre de la philosophie d'OAuth de ne pas partager les mots de passe.
- Ne permet pas au serveur d'autorisation d'afficher des pages de consentement ou de gérer des politiques de sécurité avancées (MFA, CAPTCHA, etc.).
Quand l'utiliser : Rarement, et seulement dans des cas très spécifiques et contrôlés. Typiquement, pour les applications de première partie hautement fiables (ex: une application mobile native développée par le même fournisseur de service que l'API). Même dans ces cas, le flux de code d'autorisation avec PKCE est souvent préférable.
Sécurité Avancée : PKCE (Proof Key for Code Exchange)
Le "Proof Key for Code Exchange" (PKCE, prononcé "pixie") est une extension du flux de code d'autorisation, conçue pour sécuriser les clients publics (applications mobiles et SPAs) qui ne peuvent pas stocker de client_secret en toute sécurité.
Le problème que PKCE résout :
Sans PKCE, un attaquant pourrait intercepter le authorization_code redirigé vers l'application publique et l'échanger lui-même contre un jeton d'accès.
Fonctionnement de PKCE :
- Le client génère une chaîne aléatoire unique appelée
code_verifier. - Il génère un
code_challengeà partir ducode_verifier(généralement via hachage SHA256 et encodage Base64Url). - Étape 1 (Requête d'autorisation) : Le client redirige l'utilisateur vers le serveur d'autorisation, en incluant le
code_challengeet la méthode de hachage (code_challenge_method). - Étape 2 (Consentement) : L'utilisateur donne son consentement, et le serveur d'autorisation redirige l'utilisateur vers le
redirect_uriavec leauthorization_code. - Étape 3 (Échange de jetons) : Le client envoie le
authorization_codeet lecode_verifier(non haché) au serveur d'autorisation pour l'échange de jetons. - Étape 4 (Validation) : Le serveur d'autorisation recalcule le
code_challengeà partir ducode_verifierreçu et vérifie qu'il correspond aucode_challengeoriginal reçu lors de l'étape 1. S'ils correspondent, il délivre les jetons.
Si un attaquant intercepte le authorization_code, il ne pourra pas l'échanger sans le code_verifier original, que seul le client légitime connaît.
Quand l'utiliser : Toujours pour les clients publics (SPAs, applications mobiles, applications desktop natives) qui utilisent le flux de code d'autorisation. C'est la norme de sécurité actuelle pour ces types d'applications.
Conclusion : Maîtriser l'Autorisation Déléguée
OAuth 2.0 est un standard puissant et flexible pour l'autorisation déléguée, essentiel dans le développement d'applications web modernes. Comprendre ses concepts fondamentaux et savoir quel flux utiliser pour quel scénario est crucial pour bâtir des applications sécurisées et interopérables.
- Leçon clé : OAuth 2.0 concerne l'autorisation, pas l'authentification. Il permet à une application d'agir au nom d'un utilisateur sans connaître ses identifiants.
- Choisissez le bon flux :
- Authorization Code Flow (avec ou sans PKCE) : Le choix par défaut et le plus sécurisé pour la plupart des applications (web, mobile, SPA). PKCE est obligatoire pour les clients publics.
- Client Credentials Flow : Idéal pour les communications de machine à machine (service à service).
- Implicit Flow et Resource Owner Password Credentials Flow : Généralement à éviter en raison de leurs failles de sécurité inhérentes ou de leurs risques élevés.
En suivant ces principes et en implémentant scrupuleusement les meilleures pratiques de sécurité (HTTPS, validation des URI de redirection, utilisation de state et PKCE), vous pouvez intégrer des services tiers et protéger les données de vos utilisateurs de manière robuste et fiable. OAuth 2.0 est la pierre angulaire de l'interconnexion sécurisée dans le monde numérique d'aujourd'hui.