Je me souviens avoir été quelque peu déboussolé en listant la documentation de Laravel sur ce qui concerne les utilisateurs. Vous avez forcément déjà entendu parler des packages Laravel Sanctum, Breeze, Fortify, Jetstream ou encore Passport censés nous faire gagner du temps sur la gestion des utilisateurs. Si comme moi vous êtes un peu perdu.e, nous allons clarifier tout cela ensemble.
Un existant à l'installation
Commençons par générer une installation fraîche de Laravel, lançons les migrations et constatons ce qu'il en est au niveau utilisateurs.
En base de données nous avons déjà 3 tables sur 5 qui concernent les utilisateurs
password_resets
qui comme son nom l'indique servira à la régénération des mots de passe.personnal_access_tokens
généré par Sanctum (nous y reviendrons)users
qui est la table de base des utilisateurs avec globalement quelques champs simples de nom, email, mot de passe.
Au niveau du code publié, nous avons de base un modèle User
avec quelques traits nous permettant déjà de manipuler des objets utilisateurs, de savoir s'ils sont connectés etc.
Côté composer.json
, nous découvrons un premier acteur de l'écosystème des utilisateurs, à savoir Sanctum qui est donc embarqué par défaut. Voyons ce qu'il en est.
Sanctum
Nous venons de voir que Sanctum était embarqué par défaut dans un nouveau projet Laravel. Le rôle de Sanctum est d'apporter une version simplifiée de la gestion de tokens utilisateurs en opposition à un système OAuth plus complet. C'est cette dépendance qui ajoute la table personal_access_tokens
à la première migration et qui contient les tokens des utilisateurs.
L'idée est de pouvoir générer des jetons de longue durée aux utilisateurs pour faire une SPA, une application mobile ou une API.
Enlever Sanctum des dépendances composer ne supprimera donc pas toute la partie utilisateurs du coeur de Laravel mais uniquement la gestion des tokens.
Sanctum n'embarque pas de route (hormis celle permettant d'obtenir une clé CSRF) ni de vue, ni de contrôleur.
Du fait de son embarquement automatique, je le considère un peu comme faisant partie du coeur de Laravel donc il n'y a pas vraiment à s'en préoccuper pour l'instant.
Breeze
Breeze est ce que l'on appelle un starter kit. En quelques commandes, on génère et on publie dans notre base de code les contrôleurs et vues nécessaires à l'élaboration d'un système d'authentification (Création de compte, connexion, mot de passe oublié etc.).
Tout se base sur ce qui existe dans Laravel + Sanctum et pour rester simple, la table users
n'est même pas altérée. À nous développeurs d'ajouter des champs par la suite.
C'est une super première approche à mon sens car tout est publié (contrôleurs et vues) comme si l'on avait fait le développement nous-même. C'est de fait très simple de comprendre comment Laravel fonctionne et comment enrichir l'existant.
Voici un exemple avec le contrôleur lié à la création de compte
<?php
namespace App\Http\Controllers\Auth;
// ...
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*
* @return \Inertia\Response
*/
public function create()
{
return Inertia::render('Auth/Register');
}
/**
* Handle an incoming registration request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:'.User::class,
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
}
On y voit très clairement les différentes étapes que l'on pourra améliorer par la suite avec notre propre Form Request
et ajouter des champs supplémentaires par exemple.
Un autre avantage non négligeable est la possibilité de générer du Blade classique ou bien du React et du Vue avec Inertia.
Breeze en soit n'apporte pas de fonctionnalités supplémentaires, c'est un coup de pouce pour avoir un modèle sur lequel se calquer afin de démarrer un petit projet.
Fortify
Fortify pourrait se décrire comme une boite à outils pour la gestion des utilisateurs à interfacer soi-même avec son front-end. Très concrètement, Fortify génère, pour nous, toutes les routes nécessaires à la création de compte, connexion, gestion de mot de passe et même authentification à 2 facteurs (2FA) mais ne génère pas les vues qui vont avec.
Contrairement à Breeze, les contrôleurs ne sont pas publiés dans la base de code versionnée, ils restent dans la partie vendors
. En revanche, plusieurs Actions
sont publiées permettant d'intervenir à chaque moment clé (lors de la création de l'utilisateur, de son authentification etc.) et un Service provider
est également publié servant notamment à configurer les vues à rendre.
Prenons l'exemple d'une page de création de compte.
Nous allons dans un premier temps indiquer quelle sera la vue à utiliser pour la partie GET
dans le Service Provider
de Fortify.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Fortify::registerView(function () {
return view('auth.register');
});
// ...
}
Ensuite, nous pouvons éditer l'action liée pour personnaliser ce qui doit l'être et déclencher des événements si besoin.
<?php
namespace App\Actions\Fortify;
// ...
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* @param array<string, string> $input
*/
public function create(array $input): User
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique(User::class),
],
'password' => $this->passwordRules(),
])->validate();
// ICI nous pouvons ajouter des choses
return User::create([
'name' => $input['name'],
'email' => $input['email'],
// ICI nous pouvons ajouter de nouveaux champs utilisateur
'password' => Hash::make($input['password']),
]);
}
}
Il nous restera plus qu'à créer une vue avec un formulaire de création de compte qui devra envoyer ses données en POST sur une route précise à savoir /register
.
C'est parfois déstabilisant car on doit oublier les automatismes de 1. créer une route, 2. créer une action dans un contrôleur et 3. retourner une vue depuis le contrôleur. Si les URL de base de Fortify ne vous conviennent pas, il va falloir les désactiver et recréer les vôtres ce qui demande un effort supplémentaire.
En contrepartie, la quantité de fichiers publiés dans la base de code versionnée est très limitée. On retrouve les actions sur lesquelles on peut intervenir, une migration qui ajoute des champs de 2FA dans la table des utilisateurs, un Service Provider
et un fichier de configuration. J'apprécie ce fonctionnement "non polluant" permettant un retour en arrière plus simple par la suite.
Je suis au final assez mitigé sur l'utilisation de Fortify. D'un côté cela peut faire gagner un temps précieux sur ce qui peut paraitre un peu répétitif (des CRUD, des envois de notifications, des vérifications de mot de passe), de l'autre côté on perd légèrement la main sur ce que l'on produit et j'aime encore bien me dire que je maîtrise 100% de mon code.
Jetstream
Jestream est un autre starter kit qui à la différence de Breeze se base sur Fortify. Cela signifie comme nous venons de le voir que les contrôleurs liées aux actions des utilisateurs ne sont toujours pas publiées et que l'on retrouvera les actions de Fortify dans le dossier Actions.
En revanche, comme pour Breeze, on nous a pré-mâché le travail en créant pour nous les vues nécessaires et en faisant tout le câblage avec Fortify. Cette fois, on va un peu plus loin en matière de fonctionnalités.
- Le 2FA est activé par défaut
- La gestion des sessions fait son apparition avec la possibilité de se déconnecter des autres sessions (ajout d'une table
sessions
) - Un champ
current_team_id
est ajouté à la tableusers
car il est possible d'activer une fonctionnalitéTeams
nous aidant à créer les prémisses du prochain réseau social à la mode. - Un champ
profile_photo_path
est également ajouté à la tableusers
permettant d'activer un système de photo de profil. - Enfin, une fonctionnalité appelée API permet sur la base de Sanctum de gérer des token utilisateurs
Évidemment tout cela n'est qu'une base qu'il vous faudra enrichir en fonction de vos besoins. Comme pour Breeze, il est possible de générer du Blade (+Livewire) ou du Vue (+Inertia) mais à manifestement pas encore de React.
Jetstream vient se placer en dernière couche par dessus Laravel, Sanctum et Fortify. Un peu plus usine à gaz à mon goût, ce package ne fait pas qu'utiliser les fonctionnalités des couches inférieures (inscription, connexion). Il vient aussi modifier la structure de la base avec des fonctionnalités dont on n'a pas nécessairement besoin (sessions, photo de profile, teams).
Passport
Passport ne fait qu'une seule chose qu'il fait très bien, la gestion d'un serveur OAuth2. C'est une fonctionnalité assez niche à mon sens car réservée à des projets de grande envergure.
Tout est prêt fonctionnellement des personal access tokens au système de scopes. 5 tables sont ajoutées pour gérer l'authentification, une quinzaine de routes ainsi que les commandes artisan nécessaires à la génération des premières clés.
Il n'y a pas d'équivalent à Breeze ou Jetstream car nous parlons ici d'API uniquement. En revanche, dès l'installation terminée, il est possible de tester son projet via Postman, Insomnia ou autre outil de cURL.
Etant donné le nombre de choses à penser lorsque l'on fait de l'OAuth, il serait vraiment dommage de se passer de Passport qui représente un réel gain de temps sans ajout de fonctionnalités futiles. Attention toutefois à bien vérifier qu'un simple token ne suffit pas auquel cas, il est préférable de se tourner vers Sanctum.
Socialite
Ce dernier package gère la connexion des utilisateurs Laravel vers de l'OAuth. Contrairement à Passeport qui fourni le serveur, ici on le consomme. Ce package ne change en rien la structure de la base de données, il permet simplement via quelques méthodes de se connecter à un Facebook, Github ou autre système OAuth et d'intercepter la réponse pour adapter la réponse envoyée à l'utilisateur et récupérer les informations fournies par le serveur.
use Laravel\Socialite\Facades\Socialite;
Route::get('/auth/redirect', function () {
return Socialite::driver('github')->redirect();
});
Route::get('/auth/callback', function () {
$user = Socialite::driver('github')->user();
// $user->token
});
Encore un package non intrusif qui fait une seule chose mais qui la fait bien, qui ne laisse aucune trace après sa désinstallation si son utilisation a été correctement encapsulée. À utiliser si besoin de se connecter à un service externe utilisant OAuth 1 ou 2.
Conclusion
Dans un idéal, j'aurais tendance à éviter tout package dont je n'ai pas réellement besoin sur mon projet.
Sanctum : c'est embarqué par défaut, je ne me pose pas vraiment la question.
Breeze : c'est non, je préfère faire moi-même en pensant TDD mais super pour commencer.
Fortify : Tout dépend du budget du projet et de son besoin mais c'est quand même très pratique pour les mots de passe, les notifications et la 2FA.
Jetstream : Je pense clairement ne jamais l'utiliser non plus mais je conçois que ce soit une bonne base de départ pour quelqu'un qui veut avancer vite et seul.
Passport : Je l'utiliserai sans hésiter si je dois faire de l'OAuth2 ce qui n'est pas mon cas pour le moment.