Le fait qu’une personne puisse se connecter ne prouve pas qu’elle est autorisée à consulter ou à modifier chaque donnée de l’application. L’authentification identifie l’utilisateur ; l’autorisation détermine ce qu’il peut faire, sur quelle ressource et sous quelles conditions. Une route peut exiger une session valide et néanmoins permettre à quelqu’un de consulter la commande d’un autre compte si le lien entre l’utilisateur et la ressource n’est pas vérifié.
Les tests d’autorisation en PHP doivent vérifier cette limite depuis les points d’entrée utilisés par l’application : par exemple, une requête HTTP vers une route web ou une API. L’objectif n’est pas de tester la manière dont un framework implémente ses politiques, mais de confirmer le comportement observable : qui peut faire quoi, quand la requête est rejetée et quelles données restent intactes.
Traduire les règles d’accès en matrice

Avant d’écrire les tests, exprimez les règles à l’aide de quatre éléments : l’acteur, l’action, la ressource et le contexte. Le contexte comprend les conditions qui modifient l’autorisation, comme l’appartenance à la même organisation, la propriété de l’enregistrement ou un état particulier. Cette structure évite de réduire l’autorisation à une liste de rôles.
- Acteur : utilisateur anonyme, membre, responsable ou administrateur.
- Action : consulter, créer, modifier, supprimer ou approuver.
- Ressource : une commande, un document, un compte ou un autre objet protégé.
- Contexte : propriétaire, organisation, état de la ressource ou relation en vigueur.
Par exemple, une règle peut autoriser un membre à consulter ses propres commandes, tandis qu’un responsable peut consulter celles de son organisation. Un administrateur peut disposer d’un accès plus étendu, sous réserve des règles réelles du produit. La matrice transforme chaque énoncé métier en cas vérifiable et met en évidence les combinaisons manquantes.
Il n’est pas nécessaire de tester toutes les permutations imaginables. Donnez la priorité aux frontières de confiance : un utilisateur sans session, deux utilisateurs de la même organisation, des utilisateurs d’organisations différentes, une personne ayant un rôle privilégié et une ressource qui ne lui appartient pas. Ajoutez les contextes particuliers qui changent la décision, comme une commande archivée si ses autorisations diffèrent de celles d’une commande active.
Préparer des scénarios d’intégration représentatifs
Préparez les données de façon explicite et limitée. Un test type peut créer deux organisations, un utilisateur dans chacune et une ressource associée à l’une d’elles. Authentifiez ensuite l’utilisateur qui tente d’accéder à la ressource et envoyez une requête à la route publique de l’application en utilisant l’identifiant de cette ressource. Vous testez ainsi conjointement le point d’entrée, l’authentification, l’autorisation et la réponse.
Pour chaque règle importante, incluez au moins un cas autorisé et un cas refusé. Si le propriétaire peut modifier une ressource, vérifiez que la modification autorisée fonctionne et qu’un autre utilisateur ne peut pas la reproduire. Un cas positif est essentiel : une suite qui n’attend que des refus pourrait réussir même si l’application bloquait aussi les personnes autorisées.
Vérifiez également le cas d’une ressource inexistante. La réponse à un identifiant inconnu peut différer de celle renvoyée pour une ressource existante à laquelle l’utilisateur n’a pas accès. Certaines applications renvoient une réponse « introuvable » afin de ne pas révéler l’existence de la ressource ; d’autres indiquent que l’accès est interdit. Le test doit refléter la politique délibérée du produit, et non imposer une convention universelle.
Utilisez des factories, des constructeurs de fixtures ou des helpers de test qui produisent des états valides et lisibles. Évitez de dépendre d’identifiants fixes, de l’ordre d’exécution ou de données partagées qu’un autre test pourrait modifier. Si la persistance fait partie du comportement que vous souhaitez vérifier, contrôlez le résultat dans la base de données à l’aide des outils habituels du projet ; ne supposez pas qu’une réponse positive garantit à elle seule l’état correct.
Tester l’isolation entre utilisateurs et organisations
L’isolation mérite des cas spécifiques, car les erreurs surviennent souvent lorsqu’on modifie un identifiant dans l’URL ou le corps de la requête. Créez une ressource appartenant à un compte, puis tentez de la consulter, de la modifier ou de la supprimer avec une autre identité. Répétez la vérification entre organisations lorsque l’application délimite les données par entreprise. Pour les opérations critiques, testez chaque action : protéger la lecture ne prouve pas que le téléchargement, l’exportation ou la mise à jour le sont également.
Pour éviter de dupliquer toute la suite, partagez la préparation commune et ne paramétrez que les dimensions qui expriment la règle. Par exemple, une liste de paires acteur-ressource peut définir les combinaisons autorisées. Conservez des noms de cas concrets : « un membre d’une autre organisation ne peut pas modifier la commande » est plus explicite qu’un ensemble opaque de valeurs booléennes. Séparez les scénarios lorsque la méthode, la route ou les effets attendus diffèrent.
Évitez de tester chaque combinaison de rôles et de ressources si beaucoup ne correspondent pas à des règles distinctes. Identifiez plutôt les équivalences justifiées et conservez des cas explicites pour les exceptions et les limites. En présence de rôles hiérarchiques, ne présumez pas que l’un hérite automatiquement de toutes les autorisations d’un autre : vérifiez la règle effective définie par le produit.
Vérifier les réponses et les effets secondaires
En cas de refus, vérifiez à la fois la réponse et le fait que l’opération protégée n’a pas été exécutée. Selon l’interface, la réponse peut être une redirection, un statut indiquant un accès non autorisé ou interdit, ou une réponse signalant une ressource introuvable. Vérifiez le contrat pertinent — statut, format et, si nécessaire, message — sans coupler le test à des détails de présentation superflus.
Pour une mise à jour refusée, vérifiez que les champs sensibles restent inchangés. Pour une suppression, vérifiez que l’enregistrement est toujours disponible. Pour une opération qui génère une facture, une notification ou un événement, vérifiez que cet effet ne s’est pas produit non plus. Les assertions doivent couvrir les effets importants pour le métier, et pas seulement le code HTTP.
Une requête non autorisée ne doit pas non plus permettre des modifications partielles. Si le flux effectue plusieurs opérations, vérifiez que le refus survient avant les mutations ou que la transaction laisse le système dans un état cohérent. Il n’est pas nécessaire d’inspecter les méthodes privées pour le démontrer : observez la réponse ainsi que les données ou les effets persistés.
Maintenir des tests résistants aux changements d’implémentation
Les tests d’intégration doivent passer par une interface stable de l’application, telle qu’une route et une requête utilisant l’identité authentifiée au moyen des mécanismes de test disponibles. Évitez d’appeler directement une classe interne de politiques si vous souhaitez valider l’accès réel à une ressource : vous risqueriez de ne pas couvrir l’enregistrement de la route, le middleware ou la manière dont l’objet est chargé.
Pour autant, ne transformez pas la suite en réplique de toute l’application. Testez le contrat d’autorisation à des points représentatifs et réservez les tests unitaires aux règles pures qui nécessitent de nombreux cas de contexte. Cette combinaison aide à localiser les défaillances : un test de règle peut isoler une condition, tandis que le test d’intégration confirme que cette règle protège le flux exposé.
Lorsque les rôles, les routes ou les politiques changent, révisez la matrice avant de modifier les attentes. Un test mis à jour uniquement pour accepter le nouveau résultat peut masquer un élargissement accidentel des autorisations. Documentez la raison du changement de règle, identifiez les acteurs qui gagnent ou perdent l’accès et ajoutez des cas qui protègent les nouvelles limites.
Liste de contrôle pour examiner une modification

- L’acteur, l’action, la ressource et le contexte sont-ils définis ?
- Existe-t-il au moins un scénario autorisé et un scénario refusé pour la règle concernée ?
- L’accès entre utilisateurs ou entre périmètres de données est-il testé lorsque cela s’applique ?
- La ressource inexistante et la politique choisie pour ne pas révéler d’informations sont-elles couvertes ?
- La requête passe-t-elle par le point d’entrée qui doit être protégé ?
- Vérifie-t-on qu’un refus ne modifie pas les données et ne génère pas d’effets secondaires ?
- Les données de test sont-elles isolées, lisibles et reproductibles ?
- Les attentes reflètent-elles une décision produit plutôt qu’un détail accidentel du framework ?
Une suite utile ne démontre pas qu’« il existe des autorisations » dans l’absolu : elle démontre que les combinaisons pertinentes fonctionnent et que les combinaisons non autorisées ne franchissent pas la limite. Maintenir cette matrice avec des tests d’intégration concrets facilite l’examen des changements d’accès sans lier la sécurité à une implémentation interne spécifique.



