Chapitre 5.1 — Authn ≠ Authz & modèles
⏱️ TL;DR — Deux mots qui se ressemblent, deux questions distinctes. L’authentification (authn) répond à « qui es-tu ? » ; l’autorisation (authz) à « qu’as-tu le droit de faire ? ». On ne peut autoriser sans avoir authentifié, mais être authentifié ne donne aucun droit implicite. Pour organiser les droits, deux grands modèles : RBAC (droits par rôle : admin, formateur, apprenant) et ABAC (droits par attributs : « le propriétaire de la ressource », « membre de la même organisation »). En pratique on les combine : RBAC pour les grandes catégories, ABAC pour la question « cet utilisateur peut-il agir sur cet objet précis ? » — celle qui ferme les IDOR.
🎯 Objectifs
- Distinguer nettement authentification et autorisation et leur ordre.
- Comprendre le modèle RBAC (rôles) : forces et limites.
- Comprendre le modèle ABAC (attributs), et pourquoi il est indispensable au contrôle par objet.
- Appliquer le moindre privilège au design des droits.
Deux questions, dans l’ordre
| Authentification (authn) | Autorisation (authz) | |
|---|---|---|
| Question | Qui es-tu ? | Qu’as-tu le droit de faire ? |
| Quand | En premier (login) | Ensuite, à chaque action |
| Échoue avec | 401 Unauthorized (identité non prouvée) | 403 Forbidden (identité connue, droit refusé) |
| Exemple | « Voici mon mot de passe / ma passkey » | « Ai-je le droit de supprimer ce cours ? » |
L’ordre est logique : on ne peut décider des droits d’un utilisateur qu’après avoir établi qui il est. Mais — c’est le piège central — être authentifié ne confère aucun droit en soi. Un utilisateur connecté est juste… connecté. Chaque accès à une ressource, chaque action, doit encore passer une vérification d’autorisation. Confondre « connecté » et « autorisé » est la racine de la plupart des Broken Access Control.
⚠️ Piège — L’erreur mentale fondatrice : « l’utilisateur est connecté, donc il peut accéder à cette page/ressource ». Non. L’authentification prouve l’identité, pas le droit. Une route
/api/factures/:idprotégée par « il faut être connecté » laisse tout utilisateur connecté lire toutes les factures s’il n’y a pas, en plus, une vérification que la facture lui appartient. Authentifié ≠ autorisé — toujours les deux.
📚 La source — Les codes HTTP prêtent à confusion :
401 Unauthorizedsignifie en réalité « non authentifié » (identité manquante/invalide), et403 Forbidden« authentifié mais non autorisé ». La distinction est détaillée sur MDN. Le nommage historique est trompeur ; retiens le sens, pas les mots.
RBAC : les droits par rôle
Le RBAC (Role-Based Access Control) attribue des rôles aux utilisateurs, et des permissions aux rôles. On ne donne pas des droits à chaque personne individuellement : on lui donne un rôle, qui porte un ensemble de permissions.
Utilisateur --a le role--> Formateur --peut--> [creer un cours, noter, voir sa classe]
Utilisateur --a le role--> Apprenant --peut--> [voir ses cours, rendre un devoir]
Utilisateur --a le role--> Admin --peut--> [tout gerer]- Forces : simple, lisible, facile à administrer (changer le rôle d’une personne met à jour tous ses droits). Convient très bien aux catégories d’actions (« un apprenant ne peut pas créer de cours »).
- Limites : le RBAC seul répond à « ce type d’utilisateur peut-il faire ce type d’action ? », mais pas à « cet utilisateur peut-il agir sur cet objet précis ? ». Un formateur a le rôle « peut noter » — mais peut-il noter la classe d’un autre formateur ? Le rôle ne le dit pas. C’est là qu’intervient l’ABAC.
ABAC : les droits par attributs
Le ABAC (Attribute-Based Access Control) décide en fonction des attributs de l’utilisateur, de la ressource et du contexte. La question typique : « l’attribut owner de la ressource est-il égal à l’id de l’utilisateur ? », « l’utilisateur et la ressource appartiennent-ils à la même organisation ? », « est-on dans la fenêtre horaire autorisée ? ».
Peut modifier le cours SI cours.formateurId == utilisateur.id
Peut voir la note SI note.apprenantId == utilisateur.id
OU (utilisateur.role == Formateur ET note.classe in utilisateur.classes)C’est l’ABAC qui répond à la question par objet — précisément celle dont l’oubli crée les IDOR (chapitre 5.2). Un contrôle d’accès complet a presque toujours besoin des deux : le rôle pour le type d’action, et un contrôle d’attribut pour l’objet visé.
💡 Réflexe — Pour tout accès à une ressource, pose deux questions, pas une : (1) « ce rôle a-t-il le droit de faire ce type d’action ? » (RBAC) et (2) « cet utilisateur a-t-il le droit sur cet objet-là ? » (ABAC — appartenance, tenant). Oublier la seconde, c’est l’IDOR assuré. Les deux ensemble, systématiquement.
Combiner, et rester simple
En pratique, on combine : RBAC pour les grandes catégories (qui structure l’UI et les routes), ABAC pour l’appartenance des objets. Les frameworks fournissent des abstractions pour ça — les voters de Symfony (Partie 9), les capabilities de Moodle (Partie 11), des policies/guards côté Node. L’important n’est pas le vocabulaire mais de centraliser la logique d’autorisation dans des endroits identifiés et testés, plutôt que de l’éparpiller en if un peu partout (où l’oubli guette).
Il faut aussi éviter l’excès inverse : un système de droits trop complexe devient impossible à raisonner, et l’insécurité naît de la confusion. Vise le modèle le plus simple qui exprime tes règles réelles.
Appliquer le moindre privilège
Rappel du principe (Partie 1) appliqué aux droits : chaque rôle reçoit le minimum de permissions nécessaires. On n’accorde pas « admin » par confort ; on ne coche pas toutes les cases « au cas où ». Un nouveau rôle démarre sans droits, et on ajoute au besoin (secure by default). Ainsi, un compte compromis a des dégâts bornés.
🎯 Côté attaquant — Un attaquant authentifié (compte lambda, ou compte créé exprès) teste l’écart entre son rôle et ce qu’il peut atteindre : il appelle les endpoints d’admin (
/api/admin/...), manipule des ids d’objets qui ne sont pas à lui, cherche les actions où le contrôle par objet a été oublié alors que le contrôle par rôle est présent (ou l’inverse). Chaque endroit où « authentifié » a été confondu avec « autorisé » est une prise. Il exploite systématiquement l’oubli de la seconde question (l’objet).
🧭 Sur FormaCampus — FormaCampus combine RBAC et ABAC. RBAC : rôles
Apprenant,Formateur,Responsable,Admin, structurant les actions permises (un apprenant ne crée pas de cours). ABAC : un formateur ne peut agir que sur ses classes (classe.formateurId == user.id), un apprenant ne voit que ses notes (note.apprenantId == user.id), et tout est cloisonné par organisation (le tenant — chapitre 5.3). La logique est centralisée dans des voters Symfony testés, pas dispersée. Les rôles suivent le moindre privilège :Responsablen’a pas les droits d’Admin, et un nouveau compte n’a que le strict nécessaire.
✏️ Exercices
Exercice 1 — Authn ou authz ? Classe chaque échec en 401 (authn) ou 403 (authz) : (a) l’utilisateur n’a pas envoyé de cookie de session valide ; (b) un apprenant tente d’accéder à /admin ; (c) un formateur tente de modifier la classe d’un autre formateur ; (d) le token a expiré.
✅ Solution
(a) 401 — pas d’identité valide (non authentifié). (b) 403 — identité connue (apprenant) mais droit refusé (autorisation). (c) 403 — le formateur est bien authentifié et a le rôle « peut modifier des classes », mais pas sur cet objet-là (autorisation par attribut/appartenance). (d) 401 — l’authentification n’est plus valide (identité à re-prouver).
Exercice 2 — RBAC suffit-il ? Un système n’a que du RBAC : le rôle Formateur a la permission noter. Un formateur peut-il, avec ce seul modèle, être empêché de noter la classe d’un collègue ? Sinon, qu’ajouter ?
✅ Solution
Non, le RBAC seul ne suffit pas : la permission noter est attachée au rôle, pas à un objet — tout formateur peut donc, au niveau des droits, noter n’importe quelle classe. Il manque un contrôle par objet (ABAC) : vérifier que la classe visée appartient bien au formateur connecté (classe.formateurId == user.id), ou qu’il en est responsable. On combine : RBAC (« ce rôle peut noter ») et ABAC (« cette classe est la sienne »). Sans la seconde vérification, on a un IDOR (chapitre 5.2).
🧠 Quiz de révision
1. Quelle est la différence entre authentification et autorisation ?
L’authentification répond à « qui es-tu ? » (prouver l’identité, en premier). L’autorisation répond à « qu’as-tu le droit de faire ? » (décider des droits, à chaque action). Être authentifié ne confère aucun droit en soi.
2. Que signifient réellement les codes 401 et 403 ?
401 Unauthorized = non authentifié (identité manquante/invalide), malgré son nom. 403 Forbidden = authentifié mais non autorisé (droit refusé). Le nommage historique est trompeur ; c’est le sens qui compte.
3. Que fait le RBAC et quelle est sa limite principale ?
Le RBAC attribue des permissions via des rôles (admin, formateur…). Simple et lisible pour les types d’actions. Sa limite : il ne répond pas à « cet utilisateur peut-il agir sur cet objet précis ? » — il faut un contrôle par attribut (ABAC) pour ça.
4. À quelle question répond l’ABAC que le RBAC ne couvre pas ?
À la question par objet : « l’utilisateur a-t-il le droit sur cette ressource précise ? » (appartenance : owner == user, même organisation/tenant, contexte). C’est ce contrôle dont l’oubli crée les IDOR.
5. Quelles deux questions poser pour tout accès à une ressource ?
(1) « Ce rôle peut-il faire ce type d’action ? » (RBAC) et (2) « Cet utilisateur a-t-il le droit sur cet objet-là ? » (ABAC — appartenance, tenant). Oublier la seconde = IDOR. Toujours les deux, côté serveur.
Chapitre suivant : Broken access control & IDOR — le risque n°1 des applis web, disséqué : accéder à l’objet d’un autre en changeant un identifiant.