Comment fonctionne Laravel Sanctum ?

Publié le 20 juin 2024 par Laravel Jutsu
Couverture de l'article Comment fonctionne Laravel Sanctum ?

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.

Schema de 2 applications qui communiquent

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.php
2 
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.php
2 
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.php
2 
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é.

Requêtes entre les applications

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. 🏆

Laravel Jutsu avatar
Laravel Jutsu
Détective sur sa propre scène de crime 🎱

A lire

Autres articles de la même catégorie