Authentification et sécurité : API keys, JWT, OAuth2
Le gain du jour : distinguer authentification et autorisation, connaître les trois mécanismes les plus courants pour sécuriser une API REST, et comprendre pourquoi HTTP « sans état » impose de rejouer une preuve d’identité à chaque requête.
Authentification vs autorisation : deux questions différentes
- Authentification : qui es-tu ? — prouver son identité.
- Autorisation : as-tu le droit ? — vérifier ce que cette identité peut faire.
On les code souvent ensemble, mais elles répondent à des questions distinctes — c’est
d’ailleurs exactement la nuance entre 401 Unauthorized (authentification manquante ou
invalide) et 403 Forbidden (identité connue, mais droits insuffisants) vue en leçon 2.
Rappel : pourquoi il faut prouver son identité à chaque requête
Leçon 1 : une API REST est sans état — le serveur ne garde aucune mémoire d’une
requête à l’autre. Il ne peut donc pas se souvenir « ce client s’est connecté il y a 2
minutes ». Chaque requête doit apporter sa propre preuve d’identité, généralement dans
l’en-tête Authorization.
Mécanisme 1 : les clés d’API (API keys)
Le plus simple : le serveur génère une chaîne secrète unique par client (souvent par application, pas par utilisateur final), que le client renvoie à chaque requête.
GET /orders
Authorization: Bearer sk_live_4f8a2c9b3e1d...
- ✅ Simple à générer, révoquer, faire tourner.
- ❌ Ne représente pas un utilisateur final — utile pour l’accès machine à machine (un serveur qui appelle une autre API), mal adapté quand un humain doit se connecter avec son mot de passe.
- ❌ Si elle fuite (dépôt Git public, log accidentel), elle donne un accès total jusqu’à révocation manuelle.
Mécanisme 2 : JWT — un jeton auto-porteur
Un JWT (JSON Web Token, RFC 7519) encode des informations directement dans le jeton lui-même, signées cryptographiquement par le serveur. Trois parties séparées par des points, encodées en Base64 :
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiJ9.4f8a2c9b...
└── en-tête (algo) ─┘ └────── charge utile (payload) ──────┘ └ signature ┘
La charge utile décodée (elle est lisible, pas chiffrée — ne jamais y mettre de secret) ressemble à :
{"sub": "42", "role": "admin", "exp": 1893456000}
Le serveur vérifie la signature (pas de base de données à consulter) pour confirmer
que le jeton n’a pas été altéré, et regarde exp (date d’expiration) pour le rejeter
s’il est trop vieux.
Avec une session classique, chaque requête oblige le serveur à consulter une base ou un cache (« ce jeton de session existe-t-il encore ? »). Un JWT signé se vérifie mathématiquement, sans aller interroger quoi que ce soit — cohérent avec la contrainte stateless de REST, et beaucoup plus rapide à grande échelle.
Puisqu’un JWT se vérifie sans consulter de base de données, révoquer un jeton avant son expiration naturelle est difficile — le serveur n’a par construction aucune liste centrale à jour. En pratique : jetons de courte durée de vie (quelques minutes) + un refresh token séparé, à durée de vie plus longue, stocké et révocable côté serveur.
Mécanisme 3 : OAuth2 — déléguer l’authentification à un tiers
OAuth2 (RFC 6749) répond à un problème différent : « Se connecter avec Google » sur un site tiers, sans jamais lui donner ton mot de passe Google. Le principe : le fournisseur d’identité (Google, GitHub…) délivre un jeton d’accès à l’application tierce, avec des permissions limitées (scopes — « lire mon email », pas « publier en mon nom »).
1. L'utilisateur clique « Se connecter avec Google » sur le site tiers.
2. Il est redirigé vers Google, se connecte, et approuve les permissions demandées.
3. Google redirige vers le site tiers avec un code d'autorisation temporaire.
4. Le site tiers échange ce code contre un jeton d'accès (en coulisses, serveur à serveur).
5. Le site tiers utilise ce jeton pour appeler l'API Google (ex. lire le profil).
OAuth2 résout l’autorisation déléguée (donner un accès limité à une application tierce), pas l’authentification de l’utilisateur au sens strict. C’est pour cela qu’existe OIDC (OpenID Connect), une couche construite par-dessus OAuth2 spécifiquement pour répondre à « qui est cet utilisateur ? » de façon standardisée (jeton d’identité, en plus du jeton d’accès).
Vérifie ta compréhension
1. Quelle est la différence entre authentification et autorisation ?
2. Pourquoi un JWT peut-il être vérifié sans consulter une base de données ?
3. Quel problème résout spécifiquement OAuth2 ?
À toi de jouer
Décode à la main (sans outil, juste en Base64) l’en-tête et la charge utile d’un JWT d’exemple trouvé sur jwt.io — observe qu’aucune information n’y est chiffrée, seulement signée.
Pour une API que tu conçois (fictive ou réelle), décide : accès machine à machine (clé d’API), utilisateurs humains avec mot de passe (JWT + refresh token), ou connexion déléguée à un tiers (OAuth2) ? Justifie ton choix en une phrase.
Pour aller plus loin
📖 Sources principales : RFC 7519 — JSON Web Token (JWT), RFC 6749 — The OAuth 2.0 Authorization Framework, et jwt.io pour décoder et expérimenter avec de vrais jetons.
🗂 Fiche de référence associée : Verbes, codes, en-têtes — antisèche.