Web^ID
💬 Contact 💬 Contact

08 03 2023

retour à la liste des articles

Démêlons les packages de gestion d'utilisateurs de Laravel

• écrit par [Web^ID]

visuel logos outils de gestion utilisateurs

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.

 

visuel jetstream

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 table users 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 table users 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

 

visuel 2FA
visuel token

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

Vous souhaitez démarrer rapidement ?
Besoin d'accompagnement ?

Vous voulez en savoir plus ou vous souhaitez nous parler de votre projet ?
Nous sommes à votre disposition !