Passer au contenu principal

Introduction

La réinitialisation du mot de passe est un flux d’authentification indispensable. Les kits de démarrage la construisent automatiquement, mais pour un projet API uniquement ou une UI personnalisée, il faut l’implémenter manuellement. Quand implémenter manuellement :
  • Backend d’API seulement (frontend SPA ou application mobile)
  • Construction d’une UI d’authentification sans kit de démarrage
  • Personnalisation complète des e-mails et de l’URL de réinitialisation
Si vous avez créé votre projet avec un kit de démarrage (laravel new), la réinitialisation du mot de passe est déjà en place. Cette page explique l’implémentation sans kit.
Vue d’ensemble du flux :

Configuration

La configuration se fait dans config/auth.php sous la clé passwords.
// config/auth.php

'passwords' => [
    'users' => [
        'driver' => 'database',
        'provider' => 'users',
        'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
        'expire' => 60,
        'throttle' => 60,
    ],
],
  • driver — mode de stockage (database ou cache)
  • expire — durée de validité du token en minutes (60 par défaut)
  • throttle — délai (secondes) avant qu’un nouveau lien puisse être demandé

Drivers

Driver database

Driver par défaut. Il stocke les tokens dans la table password_reset_tokens. Cette table fait partie de la migration par défaut (0001_01_01_000000_create_users_table.php).
'passwords' => [
    'users' => [
        'driver' => 'database',
        'provider' => 'users',
        'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
        'expire' => 60,
        'throttle' => 60,
    ],
],

Driver cache

Option nouvelle disponible depuis Laravel 11. Elle ne nécessite pas de table dédiée, ce qui simplifie la configuration.
Le driver cache stocke les tokens dans le cache. Aucune migration de table n’est requise. Comme la clé de cache est l’e-mail de l’utilisateur, veillez à ne pas réutiliser cette clé ailleurs dans l’application.
'passwords' => [
    'users' => [
        'driver' => 'cache',
        'provider' => 'users',
        'store' => 'passwords', // Optionnel : store de cache dédié
        'expire' => 60,
        'throttle' => 60,
    ],
],
Spécifier un store dédié évite que php artisan cache:clear n’efface les données de reset. La valeur doit correspondre à un store défini dans config/cache.php.

Préparation du modèle

Deux traits sont nécessaires sur App\Models\User.
<?php

namespace App\Models;

use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable, CanResetPassword;

    // ...
}
  • Notifiable — nécessaire pour envoyer des notifications par e-mail
  • CanResetPassword — fournit les méthodes de génération et de vérification des tokens
Le modèle User par défaut inclut déjà ces traits. Aucune action supplémentaire n’est requise sur une installation neuve.

Implémentation du routage

Quatre routes sont nécessaires.

1. Formulaire de demande de lien

Formulaire pour saisir l’e-mail.
// routes/web.php

Route::get('/forgot-password', function () {
    return view('auth.forgot-password');
})->middleware('guest')->name('password.request');
Vue Blade correspondante :
{{-- resources/views/auth/forgot-password.blade.php --}}

<form method="POST" action="/forgot-password">
    @csrf

    <div>
        <label for="email">Adresse e-mail</label>
        <input id="email" type="email" name="email" value="{{ old('email') }}" required autofocus>
        @error('email')
            <span>{{ $message }}</span>
        @enderror
    </div>

    @if (session('status'))
        <div>{{ session('status') }}</div>
    @endif

    <button type="submit">Envoyer le lien de réinitialisation</button>
</form>

2. Traitement de l’envoi du lien

Reçoit le formulaire et envoie l’e-mail via Password::sendResetLink().
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

Route::post('/forgot-password', function (Request $request) {
    $request->validate(['email' => 'required|email']);

    $status = Password::sendResetLink(
        $request->only('email')
    );

    return $status === Password::ResetLinkSent
        ? back()->with(['status' => __($status)])
        : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');
Password::sendResetLink() retourne une constante de statut.
ConstanteDescription
Password::ResetLinkSentLien envoyé
Password::INVALID_USERAucun utilisateur pour cet e-mail
Password::RESET_THROTTLEDEnvoi limité (throttling)

3. Formulaire de réinitialisation

Affiche le formulaire pour saisir un nouveau mot de passe lorsque l’utilisateur clique sur le lien.
Route::get('/reset-password/{token}', function (string $token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');
Vue correspondante :
{{-- resources/views/auth/reset-password.blade.php --}}

<form method="POST" action="/reset-password">
    @csrf

    <input type="hidden" name="token" value="{{ $token }}">

    <div>
        <label for="email">Adresse e-mail</label>
        <input id="email" type="email" name="email" value="{{ old('email') }}" required autofocus>
        @error('email')
            <span>{{ $message }}</span>
        @enderror
    </div>

    <div>
        <label for="password">Nouveau mot de passe</label>
        <input id="password" type="password" name="password" required>
        @error('password')
            <span>{{ $message }}</span>
        @enderror
    </div>

    <div>
        <label for="password_confirmation">Confirmation du mot de passe</label>
        <input id="password_confirmation" type="password" name="password_confirmation" required>
    </div>

    <button type="submit">Réinitialiser le mot de passe</button>
</form>

4. Traitement de la réinitialisation

Reçoit le formulaire et met à jour le mot de passe via Password::reset().
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;

Route::post('/reset-password', function (Request $request) {
    $request->validate([
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|min:8|confirmed',
    ]);

    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function (User $user, string $password) {
            $user->forceFill([
                'password' => Hash::make($password),
            ])->setRememberToken(Str::random(60));

            $user->save();

            event(new PasswordReset($user));
        }
    );

    return $status === Password::PasswordReset
        ? redirect()->route('login')->with('status', __($status))
        : back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');
Constantes de statut de Password::reset() :
ConstanteDescription
Password::PasswordResetRéinitialisation réussie
Password::INVALID_TOKENToken invalide ou expiré
Password::INVALID_USERAucun utilisateur pour cet e-mail

Durée de validité du token

L’option expire de config/auth.php définit la durée en minutes (60 par défaut).
'passwords' => [
    'users' => [
        'driver' => 'database',
        'expire' => 60, // Expire au bout de 60 minutes
        'throttle' => 60,
    ],
],
Avec le driver database, les tokens expirés restent en base. Purgez-les régulièrement :
php artisan auth:clear-resets
Automatisez via le scheduler.
use Illuminate\Support\Facades\Schedule;

Schedule::command('auth:clear-resets')->everyFifteenMinutes();

Personnalisation

Utiliser une notification personnalisée

Redéfinissez sendPasswordResetNotification sur le modèle User pour personnaliser l’e-mail.
use App\Notifications\ResetPasswordNotification;

class User extends Authenticatable
{
    use Notifiable, CanResetPassword;

    /**
     * Envoie la notification de réinitialisation.
     */
    public function sendPasswordResetNotification($token): void
    {
        $url = 'https://example.com/reset-password?token='.$token;

        $this->notify(new ResetPasswordNotification($url));
    }
}

Personnaliser l’URL du lien

Dans boot de AppServiceProvider, utilisez ResetPassword::createUrlUsing() pour changer l’URL. Utile pour rediriger vers une SPA hébergée sur une autre origine.
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;

public function boot(): void
{
    ResetPassword::createUrlUsing(function (User $user, string $token) {
        return 'https://example.com/reset-password?token='.$token;
    });
}

Configuration des Trusted Hosts

Le lien de réinitialisation est généré à partir de l’en-tête Host de la requête HTTP. Pour éviter les requêtes provenant d’hôtes malveillants, configurez les Trusted Hosts dans bootstrap/app.php.
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustHosts(at: ['example.com']);
})
Vérifiez toujours la configuration Trusted Hosts en implémentant la réinitialisation, sous peine d’être exposé aux attaques par injection d’en-tête Host.

Récapitulatif

ObjectifMéthode
Envoyer un lienPassword::sendResetLink(['email' => $email])
Réinitialiser le mot de passePassword::reset($credentials, $callback)
Réinitialiser sans tableConfigurer le driver cache
Supprimer les tokens expirésphp artisan auth:clear-resets
Personnaliser la notificationSurcharger sendPasswordResetNotification
Personnaliser l’URLResetPassword::createUrlUsing()

Prochaines étapes

Introduction à l'authentification

Vue d’ensemble du système d’authentification Laravel.

Notifications

Approfondissez la personnalisation des notifications par e-mail.
Dernière modification le 13 juillet 2026