L’authentification est le contrôle de qui vous êtes ; l’autorisation, la décision à chaque requête de ce que vous pouvez faire. Tout système sûr exige les deux. L’hôtel rend la chose concrète : votre pièce d’identité à la réception, c’est l’authentification ; la carte qui ouvre la chambre 412 — et seulement la 412 — c’est l’autorisation. Ce sont deux questions différentes, posées à des moments différents, traitées par des mécanismes différents, et qui échouent de façons différentes — c’est pourquoi les systèmes qui les confondent livrent les deux types de faille.
Points clés
| Question | Réponse |
|---|---|
| Authentification (AuthN) | Qui êtes-vous ? — identifiants → identité, une fois par session |
| Autorisation (AuthZ) | Que pouvez-vous faire ? — politiques → autoriser/refuser, à chaque requête |
| Les codes HTTP | 401 = non authentifié (un nom trompeur) · 403 = identifié et refusé |
| La répartition des protocoles | OIDC/SAML/passkeys = authn · scopes OAuth/RBAC/ACL = authz |
| La répartition des échecs | AuthN échoue en prise de contrôle de compte · AuthZ échoue en élévation de privilèges |
Comment l’authentification et l’autorisation s’exécutent sur une même requête
1 POST /login (identifiants + MFA) ── AUTHENTIFICATION, une fois
← token de session / cookie : identité établie
2 GET /documents/xKd91m ── chaque requête suivante :
a · token validé → identité rétablie (machinerie authn)
b · permission évaluée → ADA peut-elle lire CE document ? (décision authz)
→ 200 les deux ont réussi
→ 401 token absent/invalide — défi WWW-Authenticate ; se connecter corrige
→ 403 token valide, permission refusée — se reconnecter ne change rien
→ 404 certaines API masquent totalement les objets interdits (RFC 9110 l'autorise)
La même séparation dans le code applicatif — on se connecte une fois, on est jugé à chaque opération :
// JavaScript / Node.js — Back4app JS SDK
// Authentication: once — who are you?
const user = await Parse.User.logIn('ada', password); // session token issued
// Authorization: every request — may YOU do THIS?
const doc = await new Parse.Query('Document').get('xKd91m');
// found if an ACL entry grants ada read · "not found" if not
doc.set('title', 'Renamed');
await doc.save(); // succeeds only if an entry grants ada WRITE // Flutter / Dart — Back4app Flutter SDK
// Authentication: once — who are you?
final user = ParseUser('ada', password, null);
await user.login(); // session token issued
// Authorization: every request — may YOU do THIS?
final response = await QueryBuilder<ParseObject>(ParseObject('Document'))
.query(); // returns only rows whose ACLs grant ada read
final doc = response.results!.first as ParseObject;
doc.set('title', 'Renamed');
await doc.save(); // succeeds only if an entry grants ada WRITE // iOS / Swift — Back4app Swift SDK
// Authentication: once — who are you?
let user = try await User.login(username: "ada", password: password)
// session token issued
// Authorization: every request — may YOU do THIS?
guard var doc = try await Document.query("objectId" == "xKd91m").first()
else { return } // found only if an ACL entry grants ada read
doc.title = "Renamed"
_ = try await doc.save() // succeeds only if an entry grants ada WRITE // Android / Kotlin — Back4app Android SDK
// Authentication: once — who are you?
val user = ParseUser.logIn("ada", password) // session token issued
// Authorization: every request — may YOU do THIS?
val doc = ParseQuery.getQuery<ParseObject>("Document").get("xKd91m")
// found if an ACL entry grants ada read · "not found" if not
doc.put("title", "Renamed")
doc.save() // succeeds only if an entry grants ada WRITE Authentification vs. autorisation, côte à côte
| Authentification | Autorisation | |
|---|---|---|
| Question | Qui êtes-vous ? | Que pouvez-vous faire ? |
| Entrées | Identifiants : mots de passe, codes MFA, passkeys, biométrie | Politiques : rôles, ACL, attributs, scopes |
| Fréquence | Une fois par session (+ step-up pour les actions sensibles) | À chaque requête, pour chaque objet |
| Produit | Une session ou un token | Une décision autoriser/refuser |
| Visible par l’utilisateur | Oui — l’écran de connexion | Rarement — elle agit de façon invisible |
| Où elle s’exécute | En bordure : couche d’identité, flux de connexion | En profondeur : couche métier et couche de données, à côté des données |
| Protocoles | OpenID Connect, SAML, WebAuthn | Scopes OAuth 2.0, moteurs RBAC/ABAC/ReBAC |
| Token emblématique | ID token — qui s’est authentifié | Access token — ce que le porteur peut faire |
| Échoue en | Prise de contrôle de compte | Élévation de privilèges, exposition de données |
Deux lignes méritent leur note de bas de page. Où elle s’exécute : l’authentification se concentre naturellement en bordure — un flux de connexion, un fournisseur d’identité — tandis que l’autorisation a sa place à côté des données qu’elle protège, parce que “cet utilisateur peut-il toucher cet objet ?” a besoin de l’objet. Échoue en : les modèles de menace sont disjoints — le credential stuffing et l’hameçonnage attaquent l’authentification (c’est pourquoi la MFA est la défense authn la plus rentable), tandis que la broken object-level authorization trône en tête des listes de sécurité des API comme l’échec authz par excellence : utilisateur connecté, mauvais objet, personne n’a vérifié.
401 et 403, précisément
Les codes de statut sont la distinction habillée en chiffres, et la RFC 9110 est exacte à ce sujet. 401 Unauthorized est le nom trompeur le plus durable de l’histoire : il signifie non authentifié — la requête “ne possède pas d’identifiants d’authentification valides”, la réponse doit porter un défi WWW-Authenticate, et présenter des identifiants peut corriger la situation. 403 Forbidden signifie que le serveur a parfaitement compris qui demandait et refuse quand même — se réauthentifier est inutile par définition. Et la spec bénit un troisième geste que les équipes sécurité adorent : répondre 404 plutôt que 403, pour qu’une ressource interdite ne confirme pas sa propre existence. Choisir le bon code n’est pas de la pédanterie ; les clients construisent leur logique de retry et de reconnexion dessus, et un 403 qui devrait être un 401 envoie les utilisateurs contre un mur au lieu d’un formulaire de connexion.
OAuth, OIDC et l’éternelle confusion
La confusion a une réponse en forme de spec. Le titre d’OAuth 2.0 est “The OAuth 2.0 Authorization Framework” — il fait circuler des permissions à portée limitée (scopes), et la spécification OpenID Connect existe précisément parce qu’OAuth seul “est incapable de fournir des informations sur l’authentification d’un utilisateur final”. OIDC ajoute la couche d’identité : un ID token qui affirme qui s’est authentifié, distinct de l’access token qui affirme ce que le porteur peut faire. Chaque bouton “Se connecter avec…” est OIDC faisant de l’authentification par-dessus la plomberie d’autorisation d’OAuth — un seul flux, les deux concepts, proprement superposés plutôt que confondus.
Les trois erreurs qui partent en production
L’autorisation côté client. Masquer le bouton Supprimer relève du design d’interface ; c’est le serveur qui décide si la suppression s’exécute, et cela relève de la sécurité. Selon l’OWASP : refuser par défaut, appliquer côté serveur, et traiter les contrôles côté client comme de simples indices d’UX. Connecté ≠ autorisé. Vérifier l’authentification mais pas la propriété de l’objet — /documents/42 servi à n’importe quelle session valide — c’est la broken object-level authorization, la classe de vulnérabilité d’API la plus courante. Le contrôle se fait par objet, par requête, sans exception. L’ordre des middlewares. Authentifier d’abord, autoriser ensuite, dans le code comme dans le concept : le middleware d’identité établit qui, puis les handlers demandent si — et un contrôle d’autorisation qui s’exécute avant que l’identité soit établie autorise silencieusement l’anonyme.
Cas d’usage courants
- Connexion à l’app + permissions sur les données — le duo quotidien : un flux d’auth, des règles par objet sur tout ce qui suit.
- Conception d’API — sémantique 401/403, tokens à scopes et contrôles au niveau objet comme langage d’erreur du contrat.
- SaaS multi-tenant — authentification partagée entre les tenants ; autorisation strictement cloisonnée à l’intérieur de chacun.
- Outils d’administration et de support — authentification step-up et autorisation élevée, délibérément traitées comme deux événements distincts.
- Contenu public + privé — la lecture anonyme comme règle d’autorisation, preuve que les deux concepts fonctionnent indépendamment.
Quel contrôle vous manque-t-il ? Matrice de décision
| Symptôme | Pièce manquante |
|---|---|
| N’importe qui avec un lien lit des données privées | Autorisation — contrôles par objet |
| Les mots de passe volés continuent de fonctionner | Authentification — ajoutez la MFA |
| Les utilisateurs se heurtent à des murs 403 après une erreur de connexion | Mauvais code — ce flux est un 401 |
| N’importe quel utilisateur connecté peut appeler les API d’admin | Autorisation — rôles, refus par défaut |
| ”Se connecter avec…” traité comme de l’autorisation | Mélange de concepts — OIDC authentifie ; les scopes autorisent |
| Boutons masqués mais endpoints ouverts | Autorisation appliquée uniquement côté client |
Limites et trade-offs
- La séparation est conceptuelle, pas toujours architecturale. Les petites apps font raisonnablement tourner les deux dans un seul stack de middlewares ; la discipline consiste à garder les contrôles distincts, pas les serveurs.
- Une authn forte ne sauve pas une authz faible. Passkeys et MFA vérifient l’identité à la perfection pour un système qui laisse ensuite n’importe qui tout lire — les échecs sont indépendants.
- L’autorisation par requête a un coût. Mettre les décisions en cache, pousser les règles dans la couche de données et indexer les permissions, voilà comment “tout vérifier” reste rapide.
- Le step-up brouille la chronologie. Les actions sensibles réauthentifient en cours de session — l’authentification n’est pas strictement “une fois”, c’est “une fois par niveau d’assurance”.
- La dérive du vocabulaire cause de vrais bugs. Les équipes qui disent “auth” pour les deux moitiés écrivent des tickets, des tests et des codes d’erreur qui les confondent ; les mots sont la défense la moins chère.
Authentification et autorisation sur Back4app
Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. L’architecture de la plateforme est cette séparation : la classe User, les sessions, la connexion sociale et l’adaptateur MFA répondent à qui vous êtes, en produisant un token de session révocable — puis les ACL, les permissions au niveau de la classe et les rôles répondent à ce que vous pouvez faire, évalués côté serveur sur chaque requête REST, GraphQL et Live Query, exactement comme le montrent les onglets de code : on se connecte une fois, on est jugé à chaque opération. La section sur les erreurs devient structurelle : l’autorisation ne peut pas rester côté client parce que Back4app l’applique derrière l’API, les objets non autorisés reviennent comme introuvables au lieu de confirmer leur existence, et le refus par défaut est une case à cocher sur une classe. Les deux questions restent séparées parce que la plateforme ne les laisse jamais fusionner.
Questions fréquentes
Quelle est la différence entre authentification et autorisation, en termes simples ?
L'authentification vérifie qui vous êtes — identifiants, codes, biométrie. L'autorisation décide de ce que vous pouvez faire — rôles, permissions, politiques. Version hôtel : présenter votre pièce d'identité à la réception, c'est l'authentification ; la carte qui ouvre votre chambre mais pas la suite, c'est l'autorisation.
Laquelle vient en premier, l'authentification ou l'autorisation ?
L'authentification, presque toujours — un système ne peut pas accorder de permissions à un inconnu. L'exception instructive : les ressources publiques sont des décisions d'autorisation prises sans authentification ; "n'importe qui peut lire ceci" reste une règle de permission, appliquée à l'anonyme.
Quelle est la différence entre une erreur 401 et une erreur 403 ?
401 signifie que la requête ne possède pas d'identifiants d'authentification valides — malgré son nom officiel "Unauthorized", il veut dire non authentifié, et se connecter peut corriger la situation. 403 signifie que le serveur sait qui vous êtes et refuse quand même — permission refusée, et se reconnecter ne change rien.
Peut-on avoir de l'autorisation sans authentification ?
Oui — chaque endpoint public en est la preuve : l'accès anonyme est une règle d'autorisation évaluée sans identité. L'inverse existe aussi : authentifié mais autorisé à ne rien faire, ce qui est exactement ce qu'un compte fraîchement créé sans rôle devrait être.
Quels protocoles gèrent l'authentification et lesquels l'autorisation ?
Authentification : mots de passe, MFA, passkeys et WebAuthn, sessions, OpenID Connect, SAML. Autorisation : rôles (RBAC), règles par attributs (ABAC), ACL, scopes OAuth 2.0, moteurs de politiques. OAuth se situe notoirement du côté de l'autorisation — sa réputation de mécanisme de connexion vient d'OpenID Connect, qui se greffe par-dessus.
OAuth, c'est de l'authentification ou de l'autorisation ?
De l'autorisation — le titre même de la spec est "The OAuth 2.0 Authorization Framework", et la spécification OpenID Connect existe précisément parce qu'OAuth seul ne peut pas attester qui s'est authentifié. Chaque vrai bouton "Se connecter avec…", c'est OIDC qui ajoute une couche d'identité par-dessus la plomberie d'OAuth.
Comment l'authentification et l'autorisation fonctionnent-elles ensemble dans une requête ?
Vous vous authentifiez une fois à la connexion, ce qui produit une session ou un token. Ensuite, à chaque requête, le serveur rétablit l'identité à partir de ce token et évalue l'autorisation pour la ressource et l'action précises. Une fois par session contre à chaque requête — cette asymétrie est toute l'architecture.
Quelles sont les erreurs les plus courantes ?
Confondre les deux dans la gestion des erreurs (un 403 là où un 401 s'impose), appliquer l'autorisation dans le client (masquer des boutons relève de l'UX, pas de la sécurité) et vérifier qu'un utilisateur est connecté mais pas qu'il possède l'objet précis — la faille de broken object-level authorization qui trône en tête des listes de sécurité des API.