En route vers Biscuit (Partie 1)
Bonjour Ă toutes et tous đ
Pour ceux qui suivent ce blog, vous savez que jâaime expliquer des trucs. đ
Jâai dĂ©couvert un nouveau jouet qui me permet dâaborder plein de sujets, comme la cryptographie asymĂ©trique, les chaĂźnes de confiance et les langages logiques.
Aujourdâhui, je vous propose ainsi de dĂ©couvrir un nouvel outil appelĂ© Biscuit. đ„
Il sâagit dâun token dâautorisation et dâauthentification pouvant ĂȘtre attĂ©nuĂ© sans avoir besoin de secret partagĂ©.
Si ce que jâai Ă©crit juste au-dessus est de lâhĂ©breu pour vous, lâarticle qui va suivre va tenter de vous donner toutes les bases pour ĂȘtre Ă mĂȘme de la comprendre.
Si vous voulez directement entrer dans le vif du sujet, un second article sera disponible, ici.
Pour ceux/celles qui sont resté(e)s, je vous propose une rétrospective de la gestion des données utilisateur éphémÚres.
On parlera dâabord, du concept des sessions et on exposera leur limites.
Puis, nous analyserons les tokens dâauthentification sans Ă©tat.
Bon, câest parti pour un trĂšs, trĂšs, long voyage. đ
Authentification avec Ă©tat
Lorsquâil est venu Ă lâidĂ©e de personnaliser le contenu des utilisateurs. Il a fallu ĂȘtre capable de savoir qui Ă©tait en train de visiter le site, pour pouvoir lui afficher le contenu qui lui correspond.
Une autre volontĂ© Ă©tait de permettre Ă lâutilisateur de possĂ©der un compte sur le site. Cela permettant Ă lâutilisateur de sâengager sur les contenus, et de pouvoir plus facilement le connaĂźtre, lui et ses habitudes. (Oui le cĂŽtĂ© Sombre de la Force est partout)
Mais qui dit compte utilisateur, dit authentification. Qui dit authentification, dit mire de login.
Pour la premiĂšre connexion de sa session de visite, il ne verra pas dâinconvĂ©nient Ă se connecter avec son mot de passe. Mais sâil doit le faire Ă chaque fois, cela risque dâĂȘtre plutĂŽt agaçant pour lui et nous risquons potentiellement de ne jamais le revoir.
Câest pour cette raison que deux concepts ont vu le jour, ceci travaillant de pair :
- les cookies
- les sessions
Sessions
LâidĂ©e est simple pour savegarder les donnĂ©es dâun utilisateur, cĂŽtĂ© serveur, nous lui ouvrons une session. Il sâagit soit dâun emplacement dans la mĂ©moire du serveur, soit dâun fichier qui va contenir toutes les informations nĂ©cessaires.
Par exemple lorsque lâutilisateur est bien connectĂ© et quâil nâest pas nĂ©cessaire de lui redemander son mot de passe dâune page Ă lâautre.
Nous pouvons reprĂ©senter nos sessions sous la forme dâun tableau ayant pour clef les ID de session et comme valeur les donnĂ©es que lâon veut stocker dans la session.
CĂŽtĂ© client, nous allons Ă©galement sauvegarder des informations sur le navigateur de lâutilisateur, il sâagit dâun petit fichier qui se nomme un cookie.
Ce cookie peut contenir des informations.
Â
Information supplémentaire
Si vous voulez plus de dĂ©tails sur ce concept je vous conseille la vidĂ©o dâHubert SablonniĂšre sur le sujet.
Si câest la premiĂšre visite, lâon demande Ă lâutilisateur de se connecter.
Si lâauthentification est un succĂšs. Nous crĂ©ons une session sur le serveur et lâon vient gĂ©nĂ©rer un cookie avec lâID de session nouvellement crĂ©Ă©.
Ce cookie est alors transmis Ă lâutilisateur par retour de requĂȘte.
Lorsque lâutilisateur rĂ©alise une requĂȘte vers une ressource privilĂ©giĂ©e sur le serveur, lâon vient lire lâID de cette session, si celle-ci existe et est valide, on laisse passer lâutilisateur, sinon on lui demande de sâauthentifier.
Ainsi, nous avons rĂ©glĂ© le problĂšme, merci au revoir ! đ
Sauf queâŠ
Scissions de sessions
⊠Non â
Dans une infrastructure mĂȘme vĂ©tuste, lorsque le trafic augmente, une seule machine ne suffit pas, on entre alors dans le monde merveilleux de lâĂ©quilibrage de charge. đ€©
Sur le papier cela semble simple, on met une machine qui sert dâagent de la circulation et qui rĂ©partit les requĂȘtes sur 2 ou plus serveurs.
Cet agent de circulation est appelé un load balancer.
Câest Ă ce moment prĂ©cis que les choses se gĂątent. Rappelez-vous les sessions sont des fichiers sur le serveur ou des cases dans sa mĂ©moire. Ce qui signifie que ce qui se passe sur le serveur 1 est totalement inconnu au serveur 2 et vice-versa.
Lorsque la premiĂšre requĂȘte arrive, pas de problĂšme. On est dans lâĂ©tat prĂ©cĂ©dent, la requĂȘte va ĂȘtre routĂ©e vers le serveur 1 par exemple, une session va ĂȘtre crĂ©Ă©e et un cookie dĂ©posĂ©.
Et maintenant Ă 50/50, la prochaine requĂȘte arrivera soit sur le serveur 1, soit sur le serveur 2.
Si câest le serveur 1, pas de problĂšme, lâutilisateur prĂ©cĂ©demment connectĂ©, le reste.
Par contre, si câest le serveur 2 qui reçoit la requĂȘte, il va lire le cookie, voir que la session nâexiste pas. Demander Ă lâutilisateur de se connecter.
Si celui-ci sâexĂ©cute, une nouvelle session est construite sur le serveur 2, et le cookie est rĂ©Ă©crit avec le numĂ©ro de session sur le serveur 2.
La situation est dĂ©sormais inverse. Si la requĂȘte tombe sur le serveur 1, celui-ci dĂ©connectera lâutilisateur et ainsi de suiteâŠ
Lâutilisateur a Ă prĂ©sent 50% de chance de se faire dĂ©connecter Ă chaque requĂȘteâŻ! đ«
Bon il faut faire quelque chose, on ne peut pas laisser la situation ainsi.
Pour cela nous allons partager les sessions.
Sessions partagées
LâidĂ©e est de remplacer des sessions stockĂ©es localement par des sessions sur le rĂ©seau.
Cela peut ĂȘtre, soit via un montage NFS (ce nâest pas bien, ne faites pas ça đ) soit via une base de donnĂ©es qui va contenir nos diffĂ©rentes sessions.
La base la plus utilisĂ©e pour ce genre dâusage est Redis, mais il en existe plein dâautres.
Les diffĂ©rents serveurs sont alors connectĂ©s Ă cette base de donnĂ©es et lâinterrogent pour rĂ©cupĂ©rer la session indexĂ©e par lâID contenu dans le cookie de requĂȘte.
Et maintenant grĂące Ă ces sessions dĂ©portĂ©es, on peut augmenter ou diminuer le nombre de serveurs, sans jamais risquer de dĂ©connecter un utilisateur. đ
En Bonus
Redis est fait pour travailler en cluster, ce qui signifie que si votre nombre de serveurs explose, vous pouvez rajouter des nĆuds sur votre cluster Redis pour accueillir la charge supplĂ©mentaire de requĂȘtes de sessions.
Le souci de cela, câest la complexitĂ© de lâinfrastructure, on a une collection de frontaux, une collection de serveurs et un cluster de sessions.
Ce serait intĂ©ressant de pouvoir de se passer dâĂ©tat tout court. Câest ce que lâon va voir tout de suite. đ
Authentification sans Ă©tat
Si vous vous rappelez, les cookies sont des fichiers locaux au navigateur de lâutilisateur et gĂ©nĂ©rĂ©s par le serveur.
Pourquoi ne pas utiliser ce concept pour y stocker la session de lâutilisateur ? đș
Cookie
Reprenons notre situation de tout Ă lâheure, lâutilisateur se connecte Ă un serveur, le serveur vĂ©rifie les cookies qui lui sont fournis.
Sâil nây a pas de cookies ou que le cookie nâa pas dâinformation valide. Le serveur gĂ©nĂšre un cookie.
Au lieu dây stocker seulement lâID de la session, nous allons y coller toute la session prĂ©cĂ©demment stockĂ©e soit sur le serveur soit sur la BDD de sessions.
Lorsque lâutilisateur revient avec son cookie, le serveur vient lire le cookie et y rĂ©cupĂšre la session de lâutilisateur.
Ici notre session dĂ©finit les droits de lâutilisateur, ainsi que son user ID.
Comme la session est stockĂ©e dans le cookie et non sur un serveur en particulier, le cookie peut alors ĂȘtre traitĂ© par nâimporte quel serveur.
On en revient donc Ă la situation de la session partagĂ©e. đ
Sauf que lĂ , encore⊠Non â
Je vous prĂ©sente Jaba, Jaba est un pirate, son plaisir dans la vie, câest de devenir administrateur sur une plateforme.
Les cookies sont, je le rappelle, des fichiers locaux au navigateur, Jaba nâa pas besoin dâavoir accĂšs au serveur.
Et il ne va pas se priver de le faire. đ
Le voici administrateur !! đ
Nous allons devoir mettre des bĂątons dans les roues de Jaba !
Signatures Numériques
Pour cela nous allons introduire un concept supplémentaire, celui-ci se nomme la signature numérique. Elle consiste à valider les données qui transitent. En clair, seul le serveur doit avoir la capacité de le faire.
Il existe deux maniÚres de signer des données
- la signature par secret
- la signature par clef asymétrique
Signature par secret
Voici un secret, il sâagit dâun grand nombre qui doit comme son nom lâindique, doit rester⊠eh bien⊠secret. đ
On peut utiliser ce secret pour venir signer nos données.
Puis lorsque lâon a le besoin, nous pouvons vĂ©rifier avec ce mĂȘme secret la validitĂ© des donnĂ©es.
Si les données sont altérées, alors la signature ne correspondra pas et la vérification lÚvera une erreur.
Mais, si la signature et les donnĂ©es sont modifiables par lâutilisateur et quâil fournit une signature compatible avec les donnĂ©es
Comment fait-on pour ĂȘtre certain que les donnĂ©es ne sont pas altĂ©rĂ©es ?
Si la signature ne correspond pas avec le secret, la punition sera la mĂȘme.
Ces deux mĂ©canismes imposent que seul le serveur est Ă mĂȘme de pouvoir modifier les donnĂ©es, ou en tout cas si celle-ci ou la signature est altĂ©rĂ©e. Le serveur sâen rendra compte tout de suite.Code python
return
=
return
=
# On génÚre des secret
= b
= b
# On génÚre des messages à signer
= b
=
# La signature corespond au message
=
# On altĂšre le message
=
=
# On altĂšre la signature
=
Le code est disponible ici.
Celui-ci renvoie.
La signature est valide
La signature n'est pas valide
La signature n'est pas valide
On voit bien ici que seul une correspondance du triplet (secret, données non falsifiées, signature valide), permet au systÚme de valider les données reçues.
Le souci est que pour vérifier, il faut obligatoirement partager le secret.
Câest pour cette raison quâun autre type de signature a Ă©tĂ© mis en place, il sâagit des clefs asymĂ©triques.
Signature par clefs asymétriques
MĂȘme principe ici nous allons gĂ©nĂ©rer un secret. Celui-ci va porter un nom diffĂ©rent, il sâagit dâune clef privĂ©e.
Contrairement au secret qui était relativement libre de choix, la clef privée respecte des rÚgles mathématiques.
Elle est donc généralement créée par un algorithme.
Cette clef privée a la capacité de générer un pendant, celui-ci se nomme clef publique.
Les mathĂ©matiques nous certifient (jusquâĂ preuve du contraire) quâil est impossible de retrouver la clef privĂ©e en connaissant la clef publique.
Le couple de clefs privĂ©e/publique est appelĂ©e un Keypair en cryptographie, jâutiliserai en consĂ©quence ce terme dans la suite.
Le mĂ©canisme de signature reste le mĂȘme que dans le cadre dâun secret. Nous utilisons la clef privĂ©e pour signer nos donnĂ©es.
Par contre, la vérification est réalisée via la clef publique et non la clef privée.
Ici de mĂȘme, si les donnĂ©es sont altĂ©rĂ©es
La vérification échouera.
Ainsi que lorsque la signature nâa pas Ă©tĂ© gĂ©nĂ©rĂ©e par la clef privĂ©e dâorigine.
Voici un petit morceau de python pour vous expliquer le fonctionnement.
On installe, la dépendance :
pip install ed25519
Code python
# On génÚre la paire de clef
=
,
## On génÚre également une paire de clef pirates
=
,
## On signe un message avec la clef privée originel
= b
=
## On fait de mĂȘme mais avec une clef privĂ©e diffĂ©rente
= b
=
### Cas nominal
### Les données ont été altérées
### Les données et la signature ont été altérées
Le code ici.
La signature est valide.
La signature a été altérée.
La signature a été altérée.
On voit ici encore une fois que seul une correspondance du triplet (clef publique, données non falsifiées, signature valide), permet au systÚme de valider les données reçues.
Exemple dâutilisation
Prenons un exemple un peu plus concret qui va démontrer la plus grande flexibilité des clefs asymétriques par rapport aux secrets.
Imaginons que vous ayez une Entreprise A
, celle-ci possĂšde les informations des utilisateurs, ainsi que leurs identifiants de connexion.
Une Entreprise B
veut pouvoir accepter les utilisateurs de lâEntreprise A
, les utilisateurs nâont aucune envie de crĂ©er un compte dans lâEntreprise B
.
LâEntreprise B
a confiance dans les tokens qui sont dĂ©livrĂ©s par lâEntreprise A
.
Elle souhaite pouvoir les vérifier.
On ne voudrait pas quâun Jaba malĂ©fique falsifie le token, si ?⊠đ
Par contre lâEntreprise A
nâa aucune confiance en lâEntreprise B
, en tout cas pas suffisamment pour lui laisser signer des tokens en se faisant passer pour lâEntreprise A
.
Avec un secret ce ne serait pas possible, mais avec une paire asymĂ©trique, ce nâest pas un problĂšme.
LâEntreprise A
peut en toute confiance partager sa clef publique avec lâEntreprise B
, celle-ci ne pourra que vérifier des signatures avec.
Les choses se passent ainsi :
- Lâutilisateur sâidentifie sur
Entreprise A
Entreprise A
vérifie les identifiantsEntreprise A
gĂ©nĂšre un token quâil signe avec sa clef privĂ©e- Lâutilisateur reçoit le token signĂ© de lâ
Entreprise A
. - Lâutilisateur transmet le token Ă lâ
Entreprise B
- Lâ
Entreprise B
vĂ©rifie le token avec la clef publique de lâEntreprise A
- Si le token est valide, lâutilisateur est connectĂ© sur lâ
Entreprise B
Lâavantage de cette technique par rapport au secret, est que la clef publique peut librement ĂȘtre envoyĂ©e dans la nature, car il est impossible de retrouver la clef privĂ©e Ă partir de la clef publique et que seule la clef publique est nĂ©cessaire Ă la vĂ©rification dâune signature. đ
La clef privĂ©e nâa donc besoin dâĂȘtre baladĂ©e quâaux endroits nĂ©cessitant la signature.
Maintenant que vous avez les bases de la cryptographie, nous pouvons passer au token cryptographique.
Token
Le Token cryptographique est la rĂ©union de donnĂ©es et dâune signature numĂ©rique de celles-ci.
LâidĂ©e est de pouvoir stocker des informations dans un cookie sans risque de les voir falsifier au retour de celui-ci.
Si le token demeure inchangé, la signature sera validée.
De ce fait, si Jaba a pour idĂ©e de modifier les informations de notre Token, alors le serveur sâen rendra compte immĂ©diatement, car les donnĂ©es ne correspondront plus avec la signature.
Si Jaba tente de modifier la signature, le serveur sâen rendra Ă©galement compte, parce que la signature ne correspondra pas au secret ou Ă la clef privĂ©e qui a signĂ© le Token.
Et lĂ , Jaba est bien embĂȘtĂ©, il ne peut plus se faire passer pour un administrateur de la plateforme. đ
Les Tokens câest bien, le souci, câest que ce nâest pas standardisĂ© et donc chacun doit mettre en place sa propre logique de vĂ©rification et de crĂ©ation des tokens.
JWT
Le JWT est une initiative de standardisation des tokens.
JWT est lâabrĂ©viation de JSON Web Token, comme son nom lâindique : il sâagit dâun JSON, mais comme son nom ne lâindique pas il contient par ailleurs une signature numĂ©rique.
Je ne traiterai que du JWS, si vous voulez en apprendre plus sur le JWE, cet article est parfait
Le JWT est composé de 3 parties :
- un entĂȘte qui dĂ©finit quel type de signature est utilisĂ© (secret ou clefs asymĂ©triques) au format JSON
- les donnĂ©es en elles-mĂȘmes au format JSON
- la signature
Attention!
Lorsque vous crĂ©z des JWT, attention au choix de lâalgorithme de signature, celui-ci vous est libre. Mais mal choisi, il peut occasionner des problĂšmes de sĂ©curitĂ©.
Ces différentes informations sont alors encodées en base64 séparé par des points.
Ce qui donne par exemple :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. // en-tĂȘte
eyJ1c2VyIjoxLCJyaWdodCI6WyJyZWFkIl19. // données
tqwenw0ShYJdia5zfeDiUvKNmD0mSf6pAkzHJ67-nFs // signature
Le format des donnĂ©es est lui-mĂȘme normalisĂ©, les champs du JSON de donnĂ©es sont appelĂ©s des claims.
Il y a des champs standards qui permettent aux bibliothĂšques dâagir dans certaines circonstances :
Le champ exp
par exemple permet de forcer lâexpiration dâun JWT.
Il en existe plein dâautres, que vous pouvez retrouver ici.
En plus de ces champs normalisés, vous pouvez en rajouter autant que vous le voulez.
Un petit code dâexemple en utilisant un secret :
return
=
=
=
=
# On créé un token valide
=
# On altÚre les données sans modifier la signature
=
=
# On modifie la signature pour la faire correspondre aux données
=
=
=
Ce code nous renvoie :
Signature valide
Signature invalide
Signature invalide
Le code est disponible ici.
Le souci du JWT est quâil est impossible dâattĂ©nuer les droits.
Prenons lâexemple suivant, dans le JWT on indique lâID de lâutilisateur, par dĂ©finition celui-ci peut alors permettre dâagir sur toutes les ressources appartenant Ă cet utilisateur.
Si nous voulons dĂ©lĂ©guer des droits Ă un service, mais ne restreindre quâĂ un certain pĂ©rimĂštre de droits.
Exemple, uniquement en lecture sur les données qui se trouve dans le bucket films.
Comment peut-on atténuer les droits du JWT�
Pour cela lâon doit rĂ©gĂ©nĂ©rer un autre JWT qui possĂšde cette attĂ©nuation de droits.
GĂ©nĂ©ralement on met en place un systĂšme dâauthentification centralisĂ© qui se charge de conserver les secrets et les clefs privĂ©es. Son rĂŽle est de vĂ©rifier les tokens ou de distribuer les clefs publiques.
Lorsque le service 1 veut faire atténuer un JWT, il transmet le nouveau payload, et reçoit un nouveau JWT. Et le transmet au service 2.
Le service 2, fait alors une nouvelle demande de vérification sur ce nouveau token.
Ici jâai reprĂ©sentĂ© le processus de vĂ©rification via un secret. Mais on aurait tout aussi bien pu le faire via une clef publique.
La vérification aurait été réalisée par Service 1, Service 2; et non le Service Auth.
Par contre, rien ne dit que ce token a vraiment âmoinsâ de droits que lâautre.
Le JWT ne certifie quâune seule chose : les donnĂ©es nâont pas Ă©tĂ© falsifiĂ©es.
Câest pour cette raison quâun nouveau systĂšme est entrĂ© dans la course.
Il sâagit du Macaron !
Macaron
Le Macaron est projet issu des laboratoires de Google.
Son idĂ©e est de crĂ©er une chaĂźne de confiance de blocs qui sâinter-vĂ©rifient comme le fait une chaĂźne de certificats SSL par exemple.
Un macaron est composé de champs normalisés
- location : est une simple chaßne, elle est stockée seulement à titre indicatif
- identifier : est un champ libre permettant de définir quel secret a été utilisé pour générer le macaron
- cid : est un caveat, câest lâĂ©quivalent des claims de JWT, il peut y en avoir de 0 Ă plusieurs, il est fortement recommandĂ© dâen mettre au moins un sinon ce macaron est le joker ultime.
- signature : la signature cryptographique du macaron, nous allons voir en détails comment celle-ci est créée
Signature
Le macaron est également un token et donc signé.
Ătant donnĂ© que nous avons ici encore une signature numĂ©rique, Jaba ne pourra pas falsifier les caveats (les droits), donc de ce point de vue on est bons Ă©galement.
La mĂ©thode de validation dâun macaron est standardisĂ©e.
VĂ©rification des caveats
Pour chaque droit que lâon dĂ©sire valider, on vient faire un âstring exactâ sur chaque caveat.
Si la signature et les caveats sont validés alors le macaron est validé.
Nous avons ici une mĂ©thode standardisĂ©e de vĂ©rification des droits en plus de la vĂ©rification de lâexactitude de ceux-ci.
Par contre, pour des droits qui nĂ©cessitent des opĂ©rations plus complexes quâun âstring equalâ, il faut dĂ©velopper un parser qui vient analyser le caveat.
Maintenant voyons comment les macarons respectent les deux conditions de gestion : chaĂźne de confiance dâattĂ©nuation de droits et de validation de ces chaĂźnes.
ChaĂźne de confiance
Le macaron a opté pour le choix du secret au lieu des clefs cryptographiques.
On rĂ©alise la signature via une fonction appelĂ©e HMAC. Elle certifie quâil est impossible de remonter au secret depuis la signature.
Câest la mĂȘme quâici.
Par contre, cela signifie que le secret qui signe le macaron doit ĂȘtre distribuĂ© pour permettre la vĂ©rification du macaron.
On choisit un secret. De prĂ©fĂ©rence ce secret doit ĂȘtre unique au macaron.
On dĂ©finit aussi un identifier, celui-ci est un indice permettant de dĂ©terminer quel secret doit-ĂȘtre utilisĂ© lors de la vĂ©rification.
On réalise alors la signature de couple (secret, identifier)
Prenons un macaron avec les caveats suivants :
cid user = 666
cid time < 2022-09-01
On utilise le premier caveat ainsi que la signature 0 pour générer une signature 1.
Puis lâon fait de mĂȘme avec le deuxiĂšme caveat et la signature 1
On peut poursuivre ce mĂ©canisme de chaĂźne avec autant de caveats que lâon veut
VĂ©rification de la chaĂźne de confiance
Pour vérifier le macaron, il est nécessaire de reconstituer la chaßne de signatures en partant du secret.
On vient successivement recalculer toutes les signatures en passant en revue chaque caveat.
La fonction HMAC Ă©tant stable, pour un secret donnĂ© et un caveat donnĂ©, la signature rĂ©sultante sera toujours la mĂȘme.
Si en bout de chaßne, la signature calculée est égale à la signature du macaron.
Alors le macaron, nâa pas Ă©tĂ© falsifiĂ©.
Lorsque le macaron est transmis Ă lâutilisateur, il lui est totalement impossible de modifier les caveats.
Lâunique champ qui peut ĂȘtre considĂ©rĂ© comme provenant de lâAutoritĂ© de signature est lâidentifier. En effet mĂȘme le premier caveat peut-ĂȘtre considĂ©rĂ© comme une attĂ©nuation.
Il est impossible de déterminer à postériori si le caveat est issu du macaron originel ou de son atténuation.
Car une Ă©volution du caveat imposerait de connaĂźtre le secret.
Simulons rapidement avec un peu de code.Code python
return
=
=
=
=
=
=
= f
+= f
+= f
return
=
=
Le code est disponible ici.
Ă chaque ajout dâun caveat
La signature Ă©volueCode python
Macaron
identifier: simple
---
caveats
---
signature: b'07f6ce323d25ab7cd0af1527e1b850532eedb0f665ed48281c09542dc39b5627'
###
Macaron
identifier: simple
---
caveats
---
cid user = 666
signature: b'de18c7cc78ff83eaecbab893b0127d9dde26f3961828509f8e30af73627be838'
###
Macaron
identifier: simple
---
caveats
---
cid user = 666
cid time < 2022-09-01
signature: b'9f148339a6baca2bffade97f92eadbf7713a24e7ab7d2e2bd3d1332de28c9a8e'
###
Si lâon tente de falsifier un caveat, alors la signature calculĂ©e va diffĂ©rer.
# on falsifie un caveat
=
Ce macaron falsifié vaut :
Macaron
identifier: simple
---
caveats
---
cid user = 1
cid time < 2022-09-01
signature: b'9f148339a6baca2bffade97f92eadbf7713a24e7ab7d2e2bd3d1332de28c9a8e'
###
Bien que les signatures soient identiques. Le premier sera validé, mais pas le second.
Macaron valide
Macaron invalide
Or, une fois que le macaron est crĂ©Ă©, les seules informations que lâon connait de lâextĂ©rieur du macaron sont :
- lâidentifier
- les caveats
- la signature
Reprenons, notre bon Jaba qui tente désespérément de devenir admin.
De fait de la propriété de la fonction HMAC, il est impossible depuis la signature du macaron de revenir à la signature précédente qui a signé le dernier caveat du macaron.
Comme notre caveat concernant lâutilisateur est le premier, cela signifie que lâon doit remonter 2 fois la signature. Les probabilitĂ©s dây arriver sont quasi nulles.
De mĂȘme que de reconstruire le macaron en connaissant seulement les caveats et pas le secret.
Un secret différent créera une signature différente.
Un macaron peut donc ĂȘtre considĂ©rĂ© comme immuable une fois crĂ©Ă©.
Il peut ainsi ĂȘtre partagĂ© avec un tiers qui peut lui-mĂȘme rajouter ses caveats, sans pour autant pouvoir supprimer ou modifier les caveats prĂ©cĂ©dents.
Voyons justement ce processus de rajout de caveats.
Atténuation
LâattĂ©nuation est lâajout de nouveaux caveats dans le but de crĂ©er un macaron avec moins de droits (Ă comprendre au minimum les caveats prĂ©cĂ©dents).
Reprenons lâexemple de tout Ă lâheure : comment attĂ©nuer le macaron pour nâaccepter que les appels sur le bucket films.
Il suffit de rajouter un caveat.
cid path begins_with /bucket/films/
Un peu de code pour tester tout cela.
On définit nos Verifiers
.
Le premier fait une comparaison classique de chaĂźne de caractĂšres.
=
return ==
Le second vĂ©rifie quâun certain pattern est respectĂ©, ici un âstarts_withâ
=
=
= r
=
return False
=
=
return False
return
Puis, on crée un objet Verifier
qui prend un secret et le macaron en entrée :
=
=
=
= False
= True
break
continue
return
Son rĂŽle va ĂȘtre dâitĂ©rer sur chaque caveat et de vĂ©rifier la signature.
On va par exemple dire que lâutilisateur 666 souhaite accĂ©der au film âRatatouilleâ (trĂšs bien dâailleurs, je le recommande ^^ ).
Nous allons vĂ©rifier que le caveat concernant le champ âpathâ commence bien par â/bucket/films/ratatouilleâ. On connait le chemin Ă©tant donnĂ© que câest la ressource qui tente dâĂȘtre accĂ©dĂ©e.
Le code est disponible ici.
Testons sans atténuation :
# le macaron provient de la requĂȘte
=
=
=
Ce qui donne le résultat suivant :
Macaron valide
Macaron invalide
Maintenant atténuons ses droits :
VĂ©rifions la restriction.
# la ressource que l'on tente d'atteindre
=
=
Macaron valide â
# la ressource que l'on tente d'atteindre
=
=
Macaron invalide â
Le macaron est donc attĂ©nuable sans avoir besoin de connaĂźtre le secret. On appelle ça de lâattĂ©nuation offline.
Par contre, pour vérifier ce macaron atténué, il faut connaßtre le secret.
Si le macaron a Ă©tĂ© fourni Ă un tiers, cela impose dâexposer une API dâauthentification qui se chargera de valider le macaron.
Prenons lâattĂ©nuation suivante
Le service 1, reçoit un macaron, le fait valider par lâAPI dâAuth.
Puis le transmet au service 2.
Celui-ci, lui-mĂȘme le fait vĂ©rifier.
LâattĂ©nuation est offline, mais pas sa vĂ©rification, le secret reste centralisĂ© et donc doit soit ĂȘtre distribuĂ©, soit nĂ©cessite un service dâauthentification tiers.
Biscuit est une proposition qui vise à la fois régler les problÚmes du JWT et ceux des Macarons.
Biscuit
Je sais que vous ĂȘtes lĂ pour Biscuit, mais câest encore vraiment trop complexe pour que ça puisse tenir ici.
On verra dans la partie 2, lâanatomie dâun Biscuit ainsi que les mĂ©canismes qui permettront Ă la fois de le sĂ©curiser et de lâattĂ©nuer.
La suite sera lĂ .
Conclusion
Si vous ĂȘtes arrivĂ© jusquâici, je vous en fĂ©liciteâŻ! đ
Un petit rĂ©capitulatif de ce que lâon a vu.
Les sessions cÎté serveur sont bien, mais exigent de conserver un état et donc une persistance.
Lorsque les infrastructures grandissent, le besoin de passer sur des mĂ©canismes dâauthentification sans Ă©tat peut se faire sentir.
Les cookies ne pouvant pas ĂȘtre fournis sans sĂ©curitĂ©, le mĂ©canisme de signature a Ă©tĂ© inventĂ©, ce qui a fait apparaĂźtre le standard JWT.
Macaron par la suite, a été une tentative de rendre ces tokens immuables et atténuables.
Mais en introduisant 2 problĂšmes, le premier est la nĂ©cessitĂ© dâune centralisation de la vĂ©rification et le second lâabsence de normalisation de la vĂ©rification du Macaron.
CritĂšres | Cookie | Token | JWT | Macaron | Biscuit |
---|---|---|---|---|---|
SĂ©curisĂ© | â | â | â | â | â |
Payload normalisĂ© | â | â | â | â | â |
VĂ©rification normalisĂ©e | â | â | â | â | â |
Immuable | â | â | â | â | â |
AttĂ©nuation offline | â | â | â | â | â |
VĂ©rifiĂ© par clef publique | â | â | â | â | â |
Peut contenir des donnĂ©es non utiles pour la vĂ©rification | â | â | â | â | â |
Biscuit a pour but de mettre une â sur chaque ligne.
Un grand merci à Geoffroy Couprie et Clément Delafargue, qui ont bien voulu prendre de leur temps pour m'expliquer les concepts que je ne comprenais pas et effectuer la relecture attentive de cet article.
Ils sont accessoirement derriĂšre Biscuit. ^^
Je vous remercie encore une fois de nâavoir lu et je vous donne rendez-vous dans la partie 2. â€ïž
Ce travail est sous licence CC BY-NC-SA 4.0.