Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Protéger une API : clés, jetons et limites

Après cette leçon: Je peux protéger une API avec une clé, un jeton et une limite de débit.

Leçon de 60 min5 commandesLab PostgreSQL et PostgREST : une base de données et une API REST dans le navigateur

Comment protège-t-on une API ?

Protéger une API web, c'est vérifier qui envoie chaque requête et limiter ce qu'elle peut faire. On s'aide de clés, de jetons et d'une limite de débit. Sans cela, n'importe qui sur Internet peut lire, changer ou saturer vos données.

Trois questions se posent dans l'ordre : qui êtes-vous, avez-vous le droit, et en demandez-vous trop ?

À la fin de cette leçon

Remarque

Je peux protéger une API avec une clé, un jeton et une limite de débit.

Mots clés

MotCe que ça veut direExemple
Authentificationprouver qui l'on est
Autorisationdécider ce que quelqu'un a le droit de faire
Clé d'APIun long secret qu'un programme envoie pour s'identifier
Jeton porteurun secret à durée limitée, envoyé dans l'en-tête AuthorizationBearer abc123
Expirationle moment où un jeton cesse d'être valide
Limite de débitun nombre maximal de requêtes accepté sur une période

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Une clé dit qui appelle

L'authentification répond à la question « qui êtes-vous ? ». Un programme envoie une clé d'API, ou un jeton, dans un en-tête de chaque requête.

L'autorisation répond à une autre question : « avez-vous le droit de faire cela ? ». Une personne identifiée peut très bien être refusée.

Exemple : une requête avec un jeton

Code: bash
GET /livres HTTP/1.1
Host: api:3000
Authorization: Bearer jeton-d-exemple-123

Le laboratoire est ouvert à dessein

Le serveur du laboratoire ne vérifie aucune clé. La base est une copie privée, à vous seul. Une vraie API, elle, refuse tout ce qui n'est pas identifié.

Préparez d'abord le catalogue, puis envoyez une fausse clé. Le serveur doit l'ignorer : la vérification est du code que vous écrivez.

Créer la table des livres

Commande
PGPASSWORD=shop psql -q -h db -U shop -c "set client_min_messages to warning; drop table if exists livres; create table livres (id serial primary key, titre text not null unique, auteur text not null, annee integer not null, exemplaires integer not null default 1 check (exemplaires >= 0), disponible boolean not null default true, resume text); insert into livres (titre, auteur, annee, exemplaires, disponible) values ('Germinal', 'Emile Zola', 1885, 3, true), ('Candide', 'Voltaire', 1759, 0, false), ('Madame Bovary', 'Gustave Flaubert', 1857, 2, true), ('La Peste', 'Albert Camus', 1947, 4, true), ('Bel-Ami', 'Guy de Maupassant', 1885, 1, true); notify pgrst, 'reload schema'"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Lire sans aucune clé

Commande
curl -s -o /dev/null -w "%{http_code}\n" "http://api:3000/livres"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Voir l'en-tête que curl envoie

Commande
curl -s -v -o /dev/null -H "X-Cle-Api: cle-secrete-1" "http://api:3000/livres" 2>&1 | grep -E '^> X-Cle-Api'

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Lire avec une fausse clé

Commande
curl -s -o /dev/null -w "%{http_code}\n" -H "X-Cle-Api: cle-secrete-1" "http://api:3000/livres"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Gardez l'empreinte de la clé, pas la clé

Un serveur n'a pas besoin de garder les clés en clair. Il garde leur empreinte, le résultat d'une fonction de hachage comme SHA-256. À chaque requête, il calcule l'empreinte de la clé reçue et la compare.

Si la liste fuit, on n'y lit pas les clés. La même clé donne toujours la même empreinte.

Calculer l'empreinte d'une clé

Commande
printf 'cle-secrete-1' | sha256sum

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Un jeton cesse de valoir à l'expiration

Un jeton porteur est émis à un instant et vaut pour une durée. Passé ce délai, le serveur le refuse et le client doit en demander un autre.

Si on vole un jeton, il ne sert que peu de temps. Le tableau suit un jeton émis à l'instant 100, valable 60 secondes.

Exemple : un jeton valable 60 secondes

InstantÂge du jetonÂge inférieur à 60 ?Verdict
13030 sOuiValide
15959 sOuiValide
16060 sNonExpiré
200100 sNonExpiré

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Une limite de débit arrête l'abus

Même un client identifié peut tout saturer par erreur. Une limite de débit refuse ses requêtes en trop, avec le code 429.

Le seau à jetons est la méthode la plus courante. Le seau contient au plus 3 jetons et en regagne 1 par seconde. Chaque requête en prend un. Sans jeton, elle est refusée.

Exemple : un seau de trois jetons

InstantJetons avantDécisionJetons après
03Acceptée2
02Acceptée1
01Acceptée0
00Refusée (429)0
11 (un regagné)Acceptée0
10Refusée (429)0
53 (quatre regagnés, plafonné à 3)Acceptée2

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Exemple : le seau en Python

Code: python
capacite = 3
jetons = 3
dernier = 0
# Changez la capacité en 2 et relancez : la suite change.
for instant in [0, 0, 0, 0, 1, 1, 5]:
    jetons = min(capacite, jetons + (instant - dernier))
    dernier = instant
    if jetons >= 1:
        jetons = jetons - 1
        print(instant, "acceptee", jetons)
    else:
        print(instant, "refusee", jetons)

Une erreur fréquente

Attention

Beaucoup pensent qu'une clé placée dans le code d'une page web reste secrète. Faux : le navigateur envoie ce code à chaque visiteur, qui peut le lire. Une clé secrète vit sur un serveur, jamais dans la page.

À propos de ce labo et de sa source: Lab PostgreSQL et PostgREST : une base de données et une API REST dans le navigateur

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.