Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

L’évolution des protocoles d’authentification

Poster un commentaire

Du bon vieux login/Mot de passe à OpenID Connect il a été inventé de nombreuses technologies pour gérer l’authentification et l’identification des utilisateurs d’une application.

 

Certaines sont obsolètes ou ont eu un destin limité, mais beaucoup cohabitent et sont encore très actives.

Alors pourquoi existent t’elles? A quels besoins répondent t’elles? Comment choisir?

La meilleure façon de répondre, me semble t’il, est de les situer dans leur évolution historique.

 

C’est ce que je vais essayer de faire dans cet article.

Les protocoles historiques

Les mots de passe

Quelle que soit l’application un utilisateur identifié est toujours vu sous la forme d’une collection d’attributs: nom, prénom, langue, âge, email, profil… C’est cette collection qui va ou non lui ouvrir des droits sur toute ou partie de l’application. La question qui se pose alors est de relier un utilisateur physique à cet ensemble.

Une des plus anciennes méthodes est le partage d’un secret entre l’utilisateur et l’application sous la forme d’un mot de passe. En réalité sous la forme d’un logon, pas spécialement secret et d’un mot de passe qui doit rester secret. L’introduction du logon sur le seul échange d’un mot de passe introduit la possibilité de découpler le secret du jeu d’attributs et permet donc de modifier le mot de passe si celui-ci est compromis.

 

L’authentification par logon/mot de passe est simple à mettre en place. Elle est également simple à utiliser… mais à condition de ne pas avoir trop d’applications.

Le problème du mot de passe est bien connu: il peut assez facilement être craqué, il faut s’en souvenir et ils sont souvent nombreux, ils sont (trop) facile à révéler à quelqu’un d’autre ce qui ouvre la porte à certains scénarios d’attaques.

Une des problèmes avec le mot de passe est leur prolifération.

  • Les utilisateurs doivent se connecter à de plus en plus de services, d’applications, de serveur
  • Les administrateurs ont de plus en plus de mal de gérer les logins des employés au fur et à mesure de leur embauche, départ, besoin…
  • Les utilisateurs ne sont pas seuls à devoir s’authentifier: des serveurs, des réseaux, des périphériques divers…
    Cela fait vite du monde

Ce modèle n’est simplement pas adapté à la vie dans une entreprise, même de petite taille.

Un progrès important est l’authentification via un domaine.

Authentification dans un domaine

Un domaine est un moyen de centraliser les logins à l’intérieur d’un système d’entreprise comme Active Directory qui s’appuie sur le protocole Kerberos. On résout ainsi le problème de la prolifération des mots de passe, l’administration devient plus simple pour les administrateurs.

C’est magique… mais à une condition tout de même: il faut que les ressources à protéger fassent partie du domaine de l’entreprise par un moyen ou un autre.

Alors que faire en dehors de l’intranet de l’entreprise? La réalité moderne est que les entreprises ont de plus en plus souvent besoin de s’interconnecter avec le monde extérieur ne serait-ce que pour prendre en charge les smartphones des collaborateurs.

 

On vient d’évoquer le succès en entreprise de solutions basées sur Kerberos. Il peut sembler naturel d’étendre Kerberos à Internet.

Cela existe, mais nous savons tous que ce n’est guère utilisé. Je ne suis pas parvenu à trouver une discussion précise à ce sujet si ce n’est une difficulté liée à la bonne synchronisation des horloges des différentes machines à travers Internet. Un timestamp est en effet nécessaire pour que Kerberos fonctionne. Ajoutons à cela que la mise en œuvre est complexe.

Donc on a besoin de l’équivalent d’un domaine, mais qui soit compatible avec les contrainte du Web pour pouvoir sortir facilement des limites d’un intranet d’entreprise et si possible simple à mettre en œuvre.

Vers de nouvelles approches

Les protocoles récents sont orientés claims. L’approche est différente, le vocabulaire aussi. Il est peut être utile d’apporter quelques précisions.

Les fournisseurs d’identité

Il n’est guère réaliste d’imaginer une sorte d’autorité omnisciente connaissant tous les logins, réseaux, serveurs, périphériques du monde entier. C’est possible sur un domaine d’entreprise, ça ne l’est pas sur Internet.

On va donc plutôt s’appuyer sur une collection d’entités totalement indépendantes qui vont gérer un ensemble plus ou moins large d’utilisateurs.

C’est ainsi que l’on a tous des comptes Live, Google, Twitter…Souvent plusieurs. On a aussi souvent tendance à utiliser certains plutôt que d’autres pour se connecter à tel ou tel service et donc remplir son profil et ses informations privées de façon différentes. Pour ma part mon compte Twitter révèle plus de choses sur moi que mon compte Hotmail qui ne sert que dans ma vie privée et ne révèle que mon nom.

 

Ces entités sont appelées fournisseurs d’identité (Identity Provider). On utilise les sigles IP ou IdP. Mais on utilise aussi un autre terme au sens un peu plus large: une autorité.

On dira qu’une application a confiance (trust) un IP donné si cette application accepte les identités fournies par cet IP. Une telle application est souvent appelée application par partie de confiance (Relying Party). Je me contenterai du terme application qui est correct et est compris par tout le monde!

Concrètement la relation de confiance est établie par l’échange d’un certificat.

 

Le défi maintenant est donc de proposer aux utilisateurs une liste d’IP et de gérer l’authentification avec n’importe lequel d’entre eux. J’ai expliqué dans un de mes articles comment fonctionne la plomberie:

https://amethyste16.wordpress.com/2014/11/25/lauthentification-federee-par-claims-les-grands-principes/

Je conseille de relire cet article avant de passer à la suite.

Claims et token

Pour que cela fonctionne il a fallut inventer une abstraction universelle qui représentent les informations utilisateur: ce sont les claims.

Les protocoles orientés claims datent du début des années 2000. Et tous les protocoles modernes d’authentification s’appuient sur les claims autant que je le sache.

J’ai donné une présentation ici:

https://amethyste16.wordpress.com/2014/11/11/gerer-lauthentification-et-les-authorisations-avec-les-claims/

 

Comment on transfère les claims? En les sérialisant à l’intérieur d’une structure appelée token (jeton). Il existe plusieurs formats, les plus notables sont SAML et JWT.

Le jeton est en réalité un peu plus que cela, c’est le résultat d’une tentative réussie d’authentification entre un IP et une application. Il contient donc également les informations nécessaires pour:

  • garantir qu’il a été produit par l’IP choisit et personne d’autre
  • le jeton n’a pu être modifié par qui que ce soit d’autre

 

Un des intérêts de l’authentification via des IP est que l’application n’a plus forcément besoin d’entretenir une base d’utilisateurs. Le fournisseur d’identité peut lui fournir les informations dont elle a besoin via la liste des claims (nom, prénom par exemple).

« Plus forcément » ai-je écris. La raison est que l’application est dépendante de ce que l’utilisateur a accepté de dévoiler à l’IP et de ce que l’IP accepte de gérer.

Ce n’est donc pas toujours suffisant. Dans le contexte d’une application d’e-commerce par exemple, on va avoir besoin d’une adresse de livraison, de gérer un panier et diverses opérations de promotion.

Ces services ne sont habituellement pas pris en charge par les IP, l’application devra s’en charger en complément des services offerts par l’IP.

Les protocoles orientés claims

Première génération

Un problème commun à tous les protocoles d’authentification est de reconnaître l’utilisateur au cours de sa navigation dans l’application une fois qu’il s’est authentifié. Il n’est évidemment pas acceptable de ré-authentifier à chaque requête!

Le schéma le plus fréquent est l’utilisation d’un cookie d’authentification. L’avantage important des cookies est d’être prise en charge automatiquement par les navigateurs.

 

Sauf que cette fois on n’est plus dans le confort d’un intranet, mais sur le web. L’application peut parfaitement choisir de faire appel à des services proposés par d’autres applications un peu partout. Je pense par exemple aux places de marché dans l’e-commerce.

Ces applications tierces ont bien entendu un besoin d’authentification et il serait agréable qu’il soit transparent à l’utilisateur. Concrètement, le fait de m’authentifier auprès de mon application favorite, m’authentifie automatiquement auprès des différents services tiers.

Ce n’est pas un scénario facile avec des cookies puisque leur portée ne va pas au delà du domaine de la requête.

 

Dès le début des années 2000 des solutions ont été apportées, les deux principaux survivants de cette époque sont SAML (c’est aussi le nom d’un format de jeton) et WS-Federation.

SAML

SAML est supporté par Azure AD et ADFS, mais rien de prêt à l’emploi dans .Net lui-même. Il est de toute façon pas bien difficile de trouver des librairies.

 

L’idée principale de SAML est d’ajouter une couche supplémentaire pour ne plus dépendre des mécanismes intégrés des navigateurs en particulier des cookies.

C’est intéressant à la fois pour résoudre le problème de traversée domaines que nous avons évoqué, mais également pour intégrer un protocole de SSO dans une application qui n’est pas une application Web.

WS-Federation

WS-Federation est un des ingrédients d’une galaxie de protocoles en WS-* qui ont été définis par un certain nombre d’éditeurs dans le but de couvrir tous les aspects de la communication entre application. Donc pas seulement l’authentification.

On connaît tous WCF par exemple qui propose une implémentation de quelques protocoles WS-*.

 

Le problème de ces protocoles est leur verbosité et leur relative complexité très souvent surdimensionnée. La tendance de nos jours est de s’orienter vers des protocoles plus léger à base de REST. De ce fait les spécifications WS-*, quoique toujours utilisées, n’ont plus l’importance qu’elles ont eu dans le passé.

Tout comme SAML, WS-Federation est une technologie mature avec un grand nombre de retours d’expérience. Mais soyons honnête, il s’agit de technologies datées. Elles ne sont pas sur le point de disparaître loin de là, mais l’innovation n’est plus dans leur camp.

Protocoles deuxième génération

Un point commun des protocoles qui ont précédés sont leur verbosité et leur complexité. La tendance de nos jours est d’aller vers du plus léger, si possible REST.

Note: REST n’est en rien une architecture. C’est plutôt un style de codage basé sur la prise en compte de contraintes. De plus REST n’est absolument pas spécifique au Web. Il se trouve qu’historiquement c’est dans ce contexte que REST a été développé. Le fait que son concepteur, Roy Fielding, soit un des architectes de Http 1.1 en est sans doute la raison.

 

Mais ce n’est pas le seul problème.

Je suis abonné à plusieurs réseaux sociaux, j’ai des courriels avec une liste de contacts auprès de plusieurs fournisseurs. Il me serait parfois utiles de pouvoir partager certaines de ces informations auprès de différents services sans avoir à laborieusement recréer mes listes de contacts à chaque fois que je m’abonne à un réseau social.

Ce besoin a donné lieu à un abominable anti-pattern que l’on rencontre encore à l’occasion:

  1. Une application A souhaite accéder à une ressource détenue par un de ses utilisateurs dans l’application B.
  2. A demande à l’utilisateur de lui révéler ses credentials pour B
  3. A utilise ces credentials pour accéder à B et récupérer les informations dont il a besoin

Il n’est pas bien difficile de voir ce qui est fondamentalement vicié dans ce « protocole ».

 

Alors comment faire?

OAuth2

OAuth a été un des premiers protocole sérieux capable de résoudre ce problème. Son histoire est mouvementée sur fond de portes qui claquent. Mais d’un point de vue historique on peut retenir ceci:

Les choses ont commencé avec OAuth 1.0 qui s’est progressivement normalisé entre 2006 et 2010. OAuth est un mini-consortium de personnes en provenance de Twitter, Google ou Yahoo et peut être d’autres.

Si OAuth 1.0 résout le problème de délégation d’accès à des ressources entre applications, il n’est pas exempt de défauts et plus particulièrement:

  • Pas de possibilité de révocation
  • Impossibilité de l’utiliser en dehors du cadre de deux applications Web

Le protocole est donc trop limité pour répondre aux besoins majeurs de l’industrie.

C’est alors que les éditeurs sont arrivés (Google, Microsoft, Yahoo) et ont essayé de faire progresser les choses en proposant OAuth Wrap (Web Resource Autorisation Profile) qui élimine les limitations de OAuth 1.0.

WRAP a introduit également un nouveau format de jeton pour préciser certains points un peu flou dans OAuth: SWT.

 

Le groupe OAuth d’origine décide alors de construire OAuth2 en réaction. Mis OAuth2 n’est compatible ni avec OAuth 1.0, ni avec WRAP même s’il en reprend quelques éléments. Notez tout de même que le choix technique fut de ne pas imposer un format particulier de jeton. C’est peut être là que SWT a laissé passer sa chance.

 

Toujours est t’il qu’aujourd’hui si on parle OAuth, on doit entendre OAuth2. Le protocole d’origine est obsolète, disons qu’il survit dans quelques applis tel un zombi.

 

En résumé, OAuth va nous donner les moyens de rendre accessible nos ressources à des applications tierces tout en gardant le contrôle, mais va aussi décrire comment réclamer des ressources disponibles à une application qui les héberge.

 

Je pense que ça vaut la peine de détailler un peu plus ce qui se passe.

On a une application A et une application B ainsi qu’un utilisateur U disposant d’un compte dans A et dans B.

Parmi les artefacts, un service AS appelé Authorization Server qui est affilé à B.

2016-03-07_15-35-15

 

  1. U navigue sur l’application A qui a besoin d’accéder à la ressource R détenue par U dans l’application B
  2. A redirige la requête vers un des points de terminaison (endpoints) de AS appelé authorization endpoint. A ajoute à la requête les informations au sujet de la ressource demandée: « cette requête vient de A qui souhaite accéder à la ressource R« .AS enclenche une expérience utilisateur qui authentifie U sur B. Une fois cette authentification réussie, AS présente une nouvelle expérience utilisateur qui en gros demande:
    « hello, voulez vous m’autoriser à accéder à R que vous détenez dans B? »
    En cas de succès, AS produit un code d’autorisation.
  3. Le navigateur renvoi le jeton vers A
  4. A se retourne lui-aussi vers AS sur un endpoint appelé token endpoint. A envoi le code reçu en (2) sur ce endpoint: »je suis le très sympathique A, voici un mot de passe qui le prouve et un code d’autorisation qui montre que je suis pote avec U« 
  5. AS vérifie tout cela et si tout se passe bien il renvoi un jeton d’autorisation pour accéder à la ressource R ainsi que d’autres infos comme par exemple la durée de vie du jeton.
  6. A vient vers B avec son jeton sous le bras. B vérifie le jeton et si tout va bien il fournit un accès à la ressource demandée
  7. A renvoi à U une expérience utilisateur qui demande l’accès à R

 

Vous vous demandez peut être l’intérêt de l’étape 2. Pourquoi ne pas simplifier le schéma en la supprimant et en récupérant le jeton directement en 5.

2 est la seule étape où l’on saisit un login/mot de passe ou tout autre credential. Si vous observez bien, la différence de fond entre 2 et 5 est que l’étape 2 se joue entre le navigateur et l’AS. L’application A n’y participe absolument pas et de fait n’a aucun moyen de récupérer les credentials de U. C’est un élément de sécurité, c’est aussi très différent de ce que l’on a pu voir avec les protocoles qui précèdent.

Ca signifie aussi qu’en tant que développeur nous n’avons pas besoin de fournir une implémentation de cette partie du protocole et ce n’est pas plus mal!

 

Il est important pour la suite de remarquer une autre différence entre OAuth et tout ce qui précède: OAuth ne cherche pas à déterminer l’identité de U, mais à savoir si on est autorisé à accéder à une ressource.

 

En général AS et B sont la même chose, par exemple Facebook. Mais OAuth ne l’impose pas. Alors comment se passe le dialogue entre AS et B? Quels claims envoyer? Là aussi la norme n’est pas très loquace et c’est du cas par cas.

Donc dire que deux librairies sont compatibles OAuth2, ne signifie pas qu’elle sauront dialoguer ensemble sans un peu de travail. Typiquement on va rencontrer dans le code une longue suite de if, un pour chaque fournisseur pris en charge par la librairie.

 

OAuth2 est plus que cela et il peut proposer d’autres types de scénarios comme l’impersonnalisation.

 

Le fait de présenter à U une expérience utilisateur pour valider certaines étapes peut également poser un problème. U n’existe pas forcément! Pensez aux services Windows par exemple.

C’est également un scénario qu’OAuth sait gérer.

OpenID

OpenID devait répondre à ce besoin.

Il a été le standard de facto, adopté par la plupart des éditeurs majeurs avant d’être sérieusement concurrencé par d’autres outils.

Une des principales difficultés est tout d’abord un protocole difficile à utiliser et semble t’il mal adapté aux applications mobiles.

Disons qu’aujourd’hui, OpenID est sur sa pente descendante.

OAuth2 à nouveau!

OAuth2 gère des autorisations, mais il manque le volet identification pour notamment implémenter un SSO. Si en principe ce n’est pas dans le périmètre de OAuth2, un hack existe pour contourner le problème. Revenons au schéma présenté ici:

2016-03-07_15-35-15

Disons que A ne souhaite pas gérer elle-même l’authentification, mais la déléguer à B. Dans la vie réelle B sera par exemple Twitter.

La séquence est la suivante:

 

  1. U tente de s’authentifier auprès de A. A déclenche les étapes 1 à 5 à l’issue de laquelle un jeton est obtenu.
  2. A choisit ensuite d’appeler une API quelconque de B qui a la particularité de renvoyer des informations relatives à U, encore qu’en fait il suffit juste de valider que la requête avec le jeton T a réussi
  3. La requête ayant réussi, A sait que U a pu prouver son identité. Si en plus on a pu trouver une API qui retourne quelques infos comme le nom, c’est cool on l’affiche!

C’est ingénieux, mais c’est un hack et il n’est pas très difficile de voir quelques fragilités là dedans surtout si on souhaite travailler avec divers fournisseurs d’identité.

 

Maintenant pas mal d’applications utilisent encore cette solution…

OpenID Connect

OpenId Connect est issu de l’équipe qui a développé OpenId, mais c’est le seul point commun. Il s’appuie sur une couche OAuth2 et est incompatible avec OpenID.

Il apporte surtout une alternative plus industrielle au hack présenté dans le chapitre qui précède.

OAuth n’impose pas de format particulier de jeton, ni même comme on l’a vu, de contenu. Mais OpenID Connect a besoin de mieux formaliser les choses.

SAML est un bon format, mais c’est du XML, c’est verbeux, c’est complexe. On a besoin d’un format léger. On a déjà parlé de SWT. Ce n’est pas lui qui a gagné la bataille.

Deux formats ont été en concurrence, JSON Token proposé par des gens de chez Google et JWT proposé par une équipe de Microsoft. C’est ce dernier qui a été choisit après avoir été amélioré par plusieurs éditeurs.

J’ai rédigé un article complet à son sujet:

https://amethyste16.wordpress.com/2014/08/30/les-jetons-jwt-ce-quun-developpeur-doit-connaitre/

Conclusion

Je pense que cette présentation vous aidera à mieux comprendre les interactions entre les différentes technologies d’authentification et plus important, vous aidera à faire des choix. En tout cas c’est mon ressentit personnel, la rédaction de cet article m’a beaucoup aidé.

 

Notez également les technologies d’avenir:

  • OAuth2
  • OpenId Connect

Notez aussi et surtout la grande volatilité de ces outils, il faut dire que ça bouge pas mal ces dernières années et ce n’est pas fini.

J’ai d’autres articles sur ce thème en préparation plus orientés développeur, mais je vous suggèrerai de lire celui-ci en attendant:

https://amethyste16.wordpress.com/2014/08/15/lauthentification-en-asp-net-un-tour-dhorizon/

C’est un peu le pendant de cet article, mais du point de vue des outils de développement .NET plutôt que des protocoles.

Bibliographie

Outre les liens que l’on trouvera dans cet article, je me suis énormément aidé d’un bouquin que je recommande:

Modern Authentication with Azure Active Directory for Web Applications

Vittorio Bertocci, l’homme aux chemises à la BHL!

MS Press

 

Achetez le, ne volez pas la version électronique. Nous avons besoin de ce genre de bouquin. Retrouver les informations que l’on y trouve avec juste un moteur de recherche prend des semaines et des semaines et une énergie considérable. Vous le rentabiliserez facilement.

Et si vous pouviez l’acheter dans une vraie librairie qui fait vivre des tas de gens autour d’elle et contribue à aviver notre curiosité, plutôt qu’Amazone…

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s