The Copenhagen Book : guide pour implémenter l’authentification dans les applications web
(thecopenhagenbook.com)- Un guide de base à consulter lors de la conception de l’implémentation de l’authentification dans les applications web, visant à combler les lacunes des ressources en ligne sur l’authentification
- Une ressource gratuite et open source, proposée selon un modèle maintenu par la communauté
- Certains contenus peuvent être empreints d’opinions ou incomplets ; il est donc préférable de l’utiliser comme ressource complémentaire plutôt que comme référence unique
- Il est recommandé de l’utiliser avec les OWASP Cheat Sheet Series, une ressource de référence sur la sécurité de l’authentification
- Les suggestions ou préoccupations peuvent être transmises en ouvrant une nouvelle issue, ce qui permet de participer à l’amélioration de la documentation
Objectif et nature du document
- The Copenhagen Book fournit des recommandations générales à consulter lors de l’implémentation de l’authentification (auth) dans les applications web
- Son mode de fonctionnement est le suivant
- Disponible gratuitement
- Open source
- Maintenu par la communauté
- Le contenu peut parfois refléter des opinions ou ne pas être complet
Ressources complémentaires et participation
- Lors de l’implémentation de l’authentification, il est recommandé de le consulter avec les OWASP Cheat Sheet Series
- Si vous avez des suggestions ou des préoccupations, vous pouvez ouvrir une nouvelle issue
1 commentaires
Commentaires sur Hacker News
Si je ne me trompe pas, cet article semble avoir été écrit par l’auteur de Lucia, une bibliothèque d’authentification populaire pour TypeScript.
Récemment, il a annoncé que la bibliothèque Lucia n’était plus, selon lui, une approche ergonomique pour implémenter l’authentification, et qu’il allait l’abandonner pour la remplacer par une série de guides écrits.
Les premiers aperçus du guide étaient agréables à lire et s’accordaient bien avec The Copenhagen Book.
https://github.com/lucia-auth/lucia
https://github.com/lucia-auth/lucia/discussions/1707
https://lucia-next.pages.dev/
Il est rare de voir quelqu’un percevoir les signes d’une explosion de complexité, reconnaître que la bibliothèque ne lui est plus utile non plus, puis se retirer humblement du chemin classique de l’embonpoint des bibliothèques
En réalité, 99 % des gens ont seulement besoin de connexion/déconnexion, et c’est extrêmement utile quand c’est fourni sous forme de bibliothèque.
Si vous devez fournir des passkeys Web 8.0 via des sockets WASM à courbes elliptiques, vous pouvez le faire vous-même ou utiliser Auth0, mais il est étrange de jeter la spécification OAuth et la liste de ses pièges à quelqu’un qui développe une appli de recettes CRUD, en lui disant de construire lui-même l’authentification.
Cette personne devrait se concentrer sur son idée réelle plutôt que de réinventer la plomberie, et beaucoup finiront par l’implémenter de travers, au point de se retrouver pratiquement sans authentification.
Cette partie est fausse : « les adresses e-mail ne sont pas sensibles à la casse »
https://thecopenhagenbook.com/email-verification
Selon les standards de l’e-mail, les adresses e-mail sont sensibles à la casse.
Si l’on met une adresse e-mail en minuscules pendant l’envoi, le message peut partir à la mauvaise personne, ce qui est dangereux pour l’authentification.
Beaucoup de grands fournisseurs d’e-mail choisissent de ne pas tenir compte de la casse, mais un site qui traite l’authentification en général devrait recommander le cas général.
https://stackoverflow.com/questions/9807909/are-email-addres...
À cela s’ajoute que l’équivalent en casse opposée d’un caractère n’est pas toujours clair, et peut même changer avec le temps. Par exemple, la majuscule allemande ß a été ajoutée à Unicode en 2008 ; en programmation générale, il vaut donc mieux éviter autant que possible de dépendre de la casse.
Le standard dit une chose, mais les implémentations se comportent autrement, et dans ce cas, suivre uniquement le texte du standard crée des problèmes dans le monde réel.
Ainsi, les e-mails sont envoyés à l’adresse avec la casse saisie au départ, et la connexion fonctionne quelle que soit la casse.
L’inconvénient est qu’on ne peut pas avoir deux utilisateurs distincts dont les adresses e-mail ne diffèrent que par la casse, mais je considère que c’est acceptable.
L’e-mail n’était pas sensible à la casse, mais le nom d’utilisateur généré à partir de l’e-mail était sensible à la casse : si l’on créait un compte avec une adresse contenant des majuscules, il fallait saisir exactement cette casse pour se connecter, et la connexion ne fonctionnait pas avec l’e-mail en mode insensible à la casse.
Puis supprimons aussi les différences de langue et de culture : des milliards de lignes de code disparaîtront, et j’entends déjà les dépôts rétrécir.
Par exemple, une entrée utilisateur contenait JohnDoe@example.com et une autre johndoe@example.com, alors qu’il s’agissait manifestement de la même personne.
Et c’était encore plus pénible parce que les valeurs provenaient de systèmes différents.
Je pense que la matrice de risques des e-mails insensibles à la casse est bien meilleure que celle des e-mails sensibles à la casse. Autrement dit, il vaut mieux convertir tous les e-mails en minuscules, et The Copenhagen Book a raison sur ce point.
Très bon. J’ai toujours été frustré par le fait que 90 % des ressources de sécurité semblent conçues pour être incompréhensibles à quiconque n’est pas expert en sécurité. C’est particulièrement vrai pour les ressources de cryptographie.
Ici, en revanche, presque toutes les pages sont claires, concises, essentielles et directement applicables, ce que j’apprécie.
La page sur les courbes elliptiques m’a toutefois paru aussi difficile à comprendre que les autres ressources de cryptographie.
Comme son fonctionnement même est mathématique, je pense qu’elle est intrinsèquement opaque.
Une fois que j’ai compris les corps finis, les courbes elliptiques et, en pratique, les groupes d’entiers, j’ai pu appréhender une grande partie de la cryptographie, et il s’agissait le plus souvent, d’une manière ou d’une autre, d’une forme du problème du logarithme discret.
Ce serait bien d’avoir aussi des documents alternatifs sur des sujets similaires. Par exemple quelque chose comme les OWASP Cheat Sheets, mais avec une approche plus pratique.
Je respecte le travail, mais je suis un peu sceptique vis-à-vis de ce document.
Le nom est assez grandiloquent. Appeler ce document comme s’il avait été écrit par des chercheurs universitaires de Copenhague, c’est un excellent coup marketing.
Lucia est bien une bibliothèque relativement populaire, mais cela ne signifie pas pour autant qu’elle promeut les bonnes pratiques, ni que son auteur doive être considéré comme une autorité dans ce domaine important.
Il y a aussi des aspects de la conception de Lucia qui ne me plaisent pas. Quand le token utilisateur est proche de l’expiration, elle suggère de prolonger la durée de vie du token existant au lieu de créer un nouveau token de sécurité.
Comme le token reste en pratique valide indéfiniment et peut continuer à être exploité, cela me semble très peu sûr et contraire à la bonne pratique de sécurité consistant à limiter la durée de vie des tokens.
Lucia comme le « Copenhagen Book » recommandent cette approche : https://thecopenhagenbook.com/sessions#session-lifetime
C’est une approche courante, généralement appelée session glissante.
Le token lui-même devrait être immuable dès le départ, donc sa durée de vie ne devrait pas pouvoir être modifiée ; c’est pourquoi le renouvellement d’un token consiste normalement à fournir un nouveau token, et non à modifier l’ancien.
Dans le premier cas, un attaquant vole le token et l’utilise indéfiniment. Dans le second, s’il vole le token puis obtient un nouveau token juste avant son expiration, il peut continuer à se faire passer pour l’utilisateur.
Si l’utilisateur est expulsé, il pourrait remarquer quelque chose, mais c’est peu probable ; et pour une bonne expérience utilisateur, il faut de toute façon une période de grâce. Sinon, les requêtes parallèles posent aussi problème aux utilisateurs légitimes.
On peut utiliser un deuxième token, c’est-à-dire un token de renouvellement, mais cela ne fait que déplacer le risque vers ce token. Il faut alors s’inquiéter du vol du token de renouvellement et de son exploitation indéfinie.
Les tokens de renouvellement sont utiles parce qu’ils évitent de consulter la base de données à chaque requête. En général, les tokens de session à courte durée de vie peuvent être vérifiés sans base de données, par exemple comme des JWT signés.
Mais on ne peut pas les révoquer en cas de vol et ils restent valides jusqu’à leur expiration ; pour limiter les dégâts, il faut donc une expiration courte.
À l’inverse, un token de renouvellement implique une consultation de la base de données. Ce n’est pas le second token en lui-même qui ajoute de la sécurité, c’est la consultation de la base de données, parce qu’on peut le supprimer de la base pour le révoquer.
Lucia, au moins dans ses exemples, consulte toujours la base de données, donc on peut révoquer un token à tout moment.
Pour réduire le risque, il faut permettre à l’utilisateur de voir ses sessions actives et de les fermer. Si possible, il est aussi préférable d’afficher l’heure, le lieu et les informations sur l’appareil. Par exemple : « Connecté hier à 00 h depuis un iPhone à Copenhague ».
On peut aussi avertir l’utilisateur lorsqu’une connexion a lieu depuis un nouveau lieu ou un nouvel appareil.
Au final, il n’existe pas de manière totalement sûre de mettre en œuvre des sessions de longue durée.
Je pense que c’est une bonne remarque, mais je ne peux pas prétendre être expert.
Il y a deux choses que tout le monde rate avec OAuth, et elles ne sont pas très visibles.
Je suis content que quelqu’un ait relevé l’une d’elles. Quand on utilise des tokens, il faut impérativement utiliser les transactions comme mécanisme de verrou distribué.
Avec les tokens de renouvellement, cette importance double, voire quadruple. Si le même token est utilisé plus d’une fois, l’utilisateur est déconnecté.
Peu importe que le système tourne sur une seule machine ou sur N machines. Si deux requêtes ou plus portant un token de renouvellement sont en cours en même temps — ce qui arrive très souvent — cela déconnecte l’utilisateur et se termine souvent par une 500.
Les tokens de renouvellement sont à usage unique.
L’autre chose que les développeurs et les frameworks d’authentification ratent, c’est le paramètre « state ».
Quand on voit la direction que prend l’authentification aujourd’hui, on a l’impression qu’on se rapproche moins d’une sécurité par l’obscurité que d’une instabilité due à l’obscurité.
Si l’état de l’application s’en mêle, il faut adapter la logique applicative à l’authentification, et l’application doit vérifier si quelqu’un a volé le token de renouvellement.
Les transactions seules ne suffisent pas. Par exemple, si l’on ouvre rapidement deux onglets, on frappera le serveur deux fois avec le token de renouvellement d’origine.
Ce document privilégie la rotation des tokens de renouvellement, mais traite aussi des difficultés évidentes en environnement clusterisé : https://datatracker.ietf.org/doc/html/rfc6819#section-5.2.2....
Plusieurs requêtes arrivent toujours en même temps. Par exemple, il est fréquent qu’un navigateur démarre avec plusieurs onglets, ou qu’une application mobile envoie plusieurs requêtes d’un coup au démarrage.
J’aimerais que davantage de sites web proposent une option du type « ne fais pas expirer ma session tant que je ne me déconnecte pas, je comprends le risque »
De nos jours, les boutons « remember me » ne servent à rien
Les expirations de session me hachent constamment la journée. GitHub m’agace particulièrement : comme je l’utilise environ une fois par semaine, ma session est toujours expirée, et il m’impose en plus l’authentification à deux facteurs, donc je dois sortir mon téléphone et saisir un code à chaque fois
L’expérience utilisateur est épouvantable, mais même sans preuve, je pense qu’obliger ainsi les gens à se reconnecter en permanence finit par les fatiguer et les rendre moins attentifs
Si l’on se connecte plusieurs fois par semaine à un site, vers la 60e connexion il devient plus facile qu’un site de phishing s’intercale. À l’inverse, si un compte auquel on se connecte rarement demande soudainement un mot de passe, cela paraît étrange et met davantage en alerte
Au final, les entreprises doivent apprendre que chaque personne a une tolérance au risque et une posture de sécurité différentes, et proposer des choix
Au passage, les expirations de session fréquentes et la 2FA de GitHub m’ont tellement agacé que je suis passé à Gitea et que j’ai désactivé l’expiration. C’était 90 % de la raison de la migration
Comme il n’est accessible que depuis mon réseau, j’ai même l’impression que la sécurité s’est améliorée. Il est tout à fait possible qu’une entreprise perde des clients à cause d’un modèle de sécurité trop rigide
En gros, si la session a été utilisée dans les 30 jours, elle est prolongée de 30 jours
https://thecopenhagenbook.com/sessions#session-lifetime
Pire encore, la session semble durer environ une à deux minutes de plus qu’une semaine, si bien que cette semaine, je me suis fait éjecter juste après avoir commencé le travail de la semaine précédente
Il y a quelques semaines, je me suis connecté juste avant une réunion récurrente pour prendre des notes, et pendant plusieurs semaines d’affilée on m’a forcé à me reconnecter au milieu de cette réunion
Il existe beaucoup de réglages capables de neutraliser ces boutons « remember me »
Personnellement, je n’ai pas eu de problème pour rester connecté à des sites web, GitHub compris
J’ai récemment découvert le protocole SRP, et je suis surpris qu’il ne soit pas plus utilisé ni davantage mentionné
C’est un protocole relativement simple qui permet de faire une preuve à divulgation nulle de connaissance et de créer en même temps un token de session entre le serveur et le client
https://en.wikipedia.org/wiki/Secure_Remote_Password_protoco...
J’aime bien ce document. Beaucoup de conseils de sécurité sont obscurs et donnent parfois l’impression d’être absurdes, comme un avocat qui conseillerait de ne rien faire du tout
Ce guide est rafraîchissant par sa concision, il est facile à suivre, clair, et j’apprécie ses recommandations directes
Je vais continuer à lire les commentaires pour voir s’il y a des objections ou des mises en garde, mais je pense que je vais le passer en revue en le comparant à mon propre projet d’authentification
Une chose que j’aimerais, ce serait une section sur JWT. Même si l’avis de l’auteur est « ne l’utilisez pas », cela me conviendrait
L’une des critiques que je fais souvent aux équipes sécurité, c’est qu’elles passent beaucoup de temps à dire ce qu’il ne faut pas faire, plutôt que de fournir en amont des outils ou des méthodes permettant aux gens de faire efficacement ce qu’ils veulent faire
On peut considérer l’e-mail comme un système plus sûr, et il peut ne pas être accessible immédiatement ou depuis n’importe où
Je me demande si « auth » ici signifie authentification (authn) ou autorisation (authz)
À première vue, cela semble vouloir dire authentification, mais ce serait bien de le préciser
Petite plainte un peu liée : les navigateurs intégrés sont en train de ruiner le web
Les navigateurs intégrés rendent impossible l’usage de l’OAuth social. Dans certains cas c’est littéralement impossible, dans d’autres c’est pratiquement impossible
Si l’on clique sur un lien dans Instagram, il s’ouvre par défaut dans le navigateur d’Instagram ; si ce lien contient « Sign in with Google », Google bloque les « navigateurs non sécurisés » comme celui d’Instagram, donc cela ne fonctionne pas
Même « Sign in with Facebook » pose problème, alors que Meta possède à la fois Instagram et Facebook. Le navigateur intégré de Facebook a des problèmes similaires
Quand on clique sur un lien dans une app comme Slack, qu’on répond ensuite à un message, puis qu’on revient au navigateur en s’attendant à retrouver la page, mais que Slack l’a avalée dans son propre navigateur et qu’elle n’existe nulle part ailleurs, c’est presque toujours inutile
Heureusement, je viens de vérifier et il existe un moyen de désactiver le navigateur intégré dans Slack