7 points par GN⁺ 2024-10-11 | 1 commentaires | Partager sur WhatsApp
  • 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

 
GN⁺ 2024-10-11
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/

    • Je me demandais s’il avait expliqué par écrit pourquoi il en était arrivé à cette conclusion, et c’était ici : https://github.com/lucia-auth/lucia/discussions/1707
      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
    • Cela dit, Lucia sera probablement très vite remplacée par une autre bibliothèque d’authentification populaire.
      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.

    • La réponse la mieux notée sur Stack Overflow que tu as liée dit plutôt l’inverse : « en pratique, aucun système de messagerie largement utilisé ne distingue des adresses différentes uniquement par 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.
    • Ma façon de faire consiste à enregistrer la casse d’origine saisie par l’utilisateur, mais à effectuer les recherches sans tenir compte de la casse.
      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.
    • Il m’est arrivé de voir des cas où, lorsqu’on s’inscrivait avec une adresse e-mail, celle-ci devenait le nom d’utilisateur de connexion.
      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.
    • Supprimons tout simplement les majuscules. Elles coûtent beaucoup trop cher. Ensuite, les fuseaux horaires ; vive UTC.
      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.
    • En théorie, c’est vrai, mais dans la pratique, j’ai vu plusieurs systèmes où le même e-mail avait été enregistré avec différentes casses à cause de bugs d’implémentation initiaux.
      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.

    • Pour résumer brièvement pourquoi la cryptographie est difficile, elle repose sur la théorie des nombres et sur l’hypothèse de complexité N! = NP, c’est-à-dire l’hypothèse de l’existence de fonctions à sens unique / à trappe.
      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

    • Le code dans le lien que tu as posté ne semble pas « prolonger » la durée de vie du token, mais prolonger la session.
      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.
    • Si l’on invalide le token et qu’on répond au client avec un nouveau token, mais que le client a déjà envoyé une nouvelle requête avec l’ancien token, cette requête sera rejetée.
    • Dans le contexte de Lucia, je ne vois pas de différence entre prolonger une session existante et créer une nouvelle session.
      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.
    • Tu sembles accorder trop d’importance au nom. Cela dit, je suis curieux de connaître les approches alternatives au remplacement des tokens de session.
      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 ».

    • Sur un réseau, il n’existe pas de « à usage unique ». Invalider immédiatement un token de renouvellement dès que le serveur le reçoit, c’est chercher les ennuis.
    • C’est trop complexe et, à mon avis, pas adapté à l’authentification courante.
      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.
    • Pour des raisons similaires, la plupart des systèmes implémentent une période de grâce pour la réutilisation des tokens 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.
    • Il est très probable que tu connaisses le document OAuth Threat Model.
      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....
    • Désolé, mais dans une application réelle, ça ne fonctionne pas comme ça.
      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

    • Ce document contient de bonnes recommandations sur la manière de gérer la durée de vie des sessions
      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
    • Pour moi, le pire, c’est Notion. Pas à cause de la fréquence, mais parce qu’il coupe réellement les sessions actives et force à se reconnecter
      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 faudrait vérifier que tu n’as pas modifié quelque chose dans les paramètres du navigateur
      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
    • Certains fournisseurs d’authentification limitent la durée de vie des tokens selon l’offre
    • Au moins, on peut profiter du théâtre sécuritaire
  • 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...

    • Son adoption a été bloquée par des brevets
  • 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’expression « comme un avocat qui conseillerait de ne rien faire du tout » me parle
      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
    • J’aimerais aussi une section sur SAML et une vue d’ensemble de haut niveau de la manière de l’implémenter
    • Pour les flux par e-mail comme la vérification d’adresse ou la réinitialisation de mot de passe, je recommande de laisser les tokens secrets valides pendant plusieurs jours s’ils sont suffisamment robustes
      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

    • Comme il traite des tokens de session, des mots de passe et de WebAuthn, cela semble couvrir les deux
  • 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

    • Les navigateurs intégrés ont beaucoup de bons usages, mais suivre des liens arbitraires n’en fait pas partie
      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