PointJS — Les choses sérieuses

L’authentification basique, c’est la base

Eric Burel
PointJS
Published in
5 min readMar 9, 2021

--

Authentiquoi?

Un serveur web reçoit de nombreuses requêtes qui proviennent de plusieurs clients :

  • “je veux accéder à la page /point-js”
  • “donne moi les 5 derniers articles de ce blog”,
  • “Super-maison-connectée, je rentre de vacances dans 2 heures, remonte le thermostat à 20° s’il te plaît” ☕

Et le serveur répond à ces requêtes, soit en renvoyant du code HTML, c’est-à-dire une page web, soit en renvoyant des données, par exemple des objets JSON:

[{ thermostat: "20", message: "OK j'ai remonté le thermostat, bon retour!"}]

Vous pouvez facilement voir les requêtes et les réponses en ouvrant les outils pour développeur de votre navigateur web. Vous trouverez un onglet “Network” ou “Réseau” qui affiche tout ce qu’il se passe.

L’authentification, c’est donc la partie de votre code qui va vérifier si l’utilisateur a bien le droit de faire cette requête.

Si je reprends l’exemple du thermostat, vous n’avez surement pas envie que n’importe quel passant équipé d’un smartphone puisse dérégler votre super chaudière connectée! 🔥

Il faut distinguer deux types de requêtes : les requêtes déclenchées lorsque l’utilisateur ouvre des pages sur un navigateur, et les requêtes déclenchées par un programme informatique (soit du code JavaScript dans le navigateur, soit un autre serveur).

🤸Cas 1: Pour les humains

Le premier cas est donc celui où l’utilisateur accède à une page web. Dans ce cas, c’est le navigateur qui gère tout, l’utilisateur se contente de rentrer l’URL de son site préféré pour ouvrir la page. Par exemple, imaginons que vous vouliez accéder à la page sécurisée https://www.medium.com/point-js/admin .

Pour comprendre ce qu’il va se passer, vous avez besoin de savoir ce qu’est un “header”. Un “header”, c’est simplement une information qui s’ajoute au contenu de la réponse du serveur, à destination du navigateur.

Par exemple, en plus de vous renvoyer le contenu d’une page web, le serveur va aussi dire “ce contenu est du code HTML”. Cela permet à votre navigateur de réagir en conséquence : afficher la page par exemple.

Pour sécuriser les pages d’un site, il faut que le serveur renvoie le header suivant dans la réponse HTTP lorsque le navigateur essaie d’accéder à une page sécurisée : WWW-Authenticate: Basic.

Le navigateur va se charger d’afficher un formulaire de connexion. Ensuite, il va ensuite gérer le header Authorization sur toutes les requêtes qui parte de l’onglet courant.

Le header Authorization contient une version encodée du nom d’utilisateur et du mot de passe. Comme ça, le serveur peut vérifier si vous avez bien le droit ou non de remonter le thermostat.

Une authentification… vraiment basique

La limite de l’authentification basique, c’est qu’elle est vraiment… basique.

Par exemple, il est quasi-impossible de créer un bouton de déconnexion, l’utilisateur doit fermer le navigateur pour être déconnecté.

🤖 Cas 2: pour les robots

Le second cas est celui où l’application fait un appel à une API via JavaScript. Par exemple, imaginons que vous vouliez obtenir la liste des derniers posts de PointJS via une API https://www.medium.com/api/point-js . Dans ce cas là, c’est au développeur (c’est-à-dire vous!) de gérer le header Authorization grace à JavaScript.

Il faut d’abord encoder le nom d’utilisateur et le mot de passe :

// avec node
“Basic “ + Buffer.from(`${login}:${password}`).toString(“base64”);
// dans la console du navigateur
“Basic “ + btoa(login + “:” + password);

Ensuite, il faudra ajouter cette valeur dans le header Authorizationde toutes les requêtes déclenchées avec fetch , axios

🔨 Un exemple avec Node.js

Place à la pratique, créons notre propre serveur Node.js securisé.

Il est assez facile de mettre en place l’authentification basique, car tous les langages de programmation fournissent des packages clé-en-main.

Le code suivant est un exemple pour Express (Node.js):

// On créé un serveur Express
const app = require("express")();
// On configure l'authentification basique
const basicAuth = require("express-basic-auth");
app.use(
basicAuth({
// on liste ici les utilisateurs qui peuvent accéder au site
users: { admin: "supersecret" },
challenge: true,
})
);
// Une réponse basique, juste pour l'exemple
app.use("/", (req, res) => { res.send("Success"); });
// On lance le serveur
app.listen(3000, () => {
console.log(`Ouvrez http://localhost:3000`);
});

En exercice, vous pouvez lancer ce serveur (je suppose que vous utilisez Linux et que vous avez installé Node.js):

  • ouvrez votre terminal et créez un nouveau dossier mkdir test-basic-auth && cd test-basic-auth
  • installez Express npm init; npm install express express-basic-auth;
  • copiez le code du serveur ci-dessus dans un fichier app.js
  • lancez node app.js
  • ensuite, si vous ouvrez http://localhost:3000 sur votre navigateur, vous verrez un message qui vous invite à vous connecter. Avec le nom d’utilisateur “admin” et le mot de passe “supersecret”, vous devriez pouvoir vous connecter.

En bonus, vous pouvez aussi lancer une requête via la console du navigateur avec le code suivant:

fetch("http://localhost:3000/", { 
headers: {
"Authorization": "Basic " + btoa("admin:supersecret")
}
})
.then(req => req.text()).then(console.log)

Dans les deux cas, si vous vous connectez avec le nom d’utilisateur “admin” et le mot de passe “supersecret”, vous devriez obtenir le message “Success”.

Et voilà, votre voisin ne pourra plus jamais hacker votre chaudière connectée !

Ce mode de connexion, qui repose entièrement sur le nom d’utilisateur et le mot de passe, n’est vraiment pas très sécurisé. On verra dans de prochains points de nouvelles approches plus modernes et plus sécurisées, comme l’authentification par token. En attendant, n’oubliez pas de suivre la publication !

--

--

Eric Burel
PointJS

Next.js teacher and course writer. Co-maintainer of the State of JavaScript survey. Follow me to learn new Next.js tricks ✨ - https://nextjspatterns.com/