Un peu de contexte
Vous y êtes. Votre application front-end est en vie !
Vous allez démarrer le développement de votre API Laravel et installer le système d'authentification qui va bien : Laravel Sanctum.
Quelques lignes de code plus tard vous vous retrouvez avec des erreurs de tous les types. Votre console clignote en rouge à base de unauthenticated
ou pire encore Access-Control-Allow-Origin
.
Pour éviter que cette histoire ne finisse en drame existentiel, je vous propose au travers de cet article de reprendre les bases.
Vous allez enfin comprendre comment se déroule l'authentification SPA avec Laravel Sanctum.
Les couches de votre API
Il faut voir votre API comme un oignon. 🧅
Elle possède de multiples couches qui la protège. Chacune représente une protection spécifique qui va accueillir la requête entrante et exécuter (ou pas) une certaine logique.
L'allégorie semble amusante mais sachez que ce sont ces couches qui nous posent le plus souvent problème.
CORS
Le CORS est une norme qui a pour rôle d'autoriser les requêtes entrantes pour certains domaines.
Partons du principe que votre application front-end vive sur le domaine my-super-app.com et que votre application Laravel existe sur api.my-super-app.com.
2 domaines différents tentent de communiquer.
Vous devez autoriser my-super-app.com à contacter votre application Laravel en notifiant ce domaine dans le fichier cors.php :
1// config/cors.php2 3return [4 'paths' => [...],5 'allowed_origins' => ['my-super-app.com'],6 'allowed_origins_patterns' => [],7 8 // ...9];
VerifyCsrfToken
Ce middleware est la seconde couche et n'est concerné que pour les requêtes de type POST, PUT, PATCH ou DELETE.
Grâce à lui, les petits malins qui essaieront d'imiter votre site ne pourront pas envoyer des requêtes malveillantes à votre serveur au nom de vos utilisateurs.
En effet, ils ne disposeront pas d'un token CSRF valide requis pour l'authentification de ces requêtes.
Ce token est généré par Laravel et gardé en session. Si lors d'une requête ils ne correspondent pas, le middleware VerifyCsrfToken considèrera la requête comme potentiellement malveillante et ne permettra pas à la requête d'aboutir.
EnsureFrontendRequestsAreStateful
Ce middleware n'a rien à voir avec la sécurité directement.
Il n'a pas le pouvoir d'autoriser ou de rejeter quelque requête que ce soit. Il va simplement tenter d'associer ladite requête à un utilisateur authentifié en allant chercher la session correspondante à cet utilisateur. Cette session aura été créé plus tôt sur le serveur durant le processus d'authentification.
En revanche, il n'authentifiera pas les requêtes qui sont absentes des domaines stateful
et renverra une réponse HTTP 401
. Et ce même si l'utilisateur a rentré des identifiants corrects.
1// config/sanctum.php2 3return [4 'stateful' => ['my-super-app.com'],5 6 // ...7];
L'API
Ce sont globalement toutes les routes qui sont protégées par le middleware auth:sanctum
.
1// routes/api.php2 3Route::middleware('auth:sanctum')->group(function (): void {4 Route::get('/user', ShowController::class)->name('user');5});
Après toutes ces vérifications, la requête entrante a montré patte blanche et peut consulter sereinement les endpoints de votre API.
C'est gagné.
Maintenant voyons comment se déroulent les différentes étapes d'authentification.
Les étapes de connexion
Une première requête
Une première requête doit être envoyée en méthode GET, disons vers /any-endpoint.
Le endpoint importe peu et la requête traversera sans souci les différentes couches si la configuration mentionnée plus haut est correcte.
Laravel va alors créer une session côté serveur, contenant un ID de session et le fameux token CSRF. Ces informations précieuses sont renvoyées au navigateur, qui s'empressera de les enregistrer dans un cookie.
Envoi du formulaire
L'application front-end peut maintenant envoyer une requête POST contenant l'email, le mot de passe de l'utilisateur, la valeur du token CSRF inclus dans l'en-tête X-XSRF-TOKEN et l'ID de session.
Cette fois-ci, le middleware VerifyCsrfToken entre en jeu car le verbe de cette requête le concerne. Laravel va lire le token CSRF lié à la session créée précédemment et vérifier que la requête contient le même token. Sinon, une erreur 419
sera renvoyée.
Lorsque la requête atteint le serveur, Laravel va chercher un utilisateur correspondant à l'email et au mot de passe fournis. Puis, il mettra à jour la session existante avec l'ID de l'utilisateur. Il renverra une réponse avec toujours les mêmes informations que la première soit l'ID de session et le token CSRF.
Une route protégée
Maintenant que l'utilisateur est connecté, il souhaite récupérer des informations sur une route particulière qui est protégée par le middleware auth:sanctum.
Il traverse la couche CORS et VerifyCsrfToken sans encombre.
C'est au tour du middleware EnsureFrontendRequestsAreStateful de prendre le relais sous condition d'avoir correctement configuré le domaine de la requête entrante dans nos SANCTUM DOMAIN STATEFUL
.
En effet, l'ID de session stockée dans le cookie et envoyée dans la requête permet à ce middleware de trouver la session correspondante et donc l'utilisateur authentifié.
Une histoire de cookie
Il faut savoir que le cookie généré côté serveur, contenant les informations liées à notre session et nous permettant de nous connecter, a une durée de vie de 2 heures par défaut.
Passé ce délai, le middleware EnsureFrontendRequestsAreStateful ne trouvera plus de session correspondante, car l'ID sera manquant, et renverra une réponse HTTP 401 unauthenticated
.
Voilà comment Laravel Sanctum fonctionne.
Félicitations, vous êtes maintenant armé(e) pour faire face aux éventuelles réponses et débugger plus facilement. 🏆
A lire
Autres articles de la même catégorie
Une architecture modulaire en Laravel
Comment appliquer une architecture modulaire à un projet Laravel.
Simplifiez l'utilisation de Reverb avec Livewire
Utiliser le serveur de broadcast Reverb sans écrire de JavaScript grâce à la magie de Livewire
Quelques tips pour phpunit #1
Quelques tips pour améliorer vos performances et votre confort d’utilisation de phpunit.