Zum Hauptinhalt springen

Einführung

Das Zurücksetzen von Passwörtern gehört zu den unverzichtbaren Authentifizierungs-Flows einer Webanwendung. Nutzen Sie ein Starter-Kit, wird diese Funktion automatisch aufgebaut. In reinen API-Projekten oder wenn Sie ein eigenes UI aufbauen, ist eine manuelle Umsetzung nötig. Wann eine manuelle Umsetzung nötig ist:
  • Reines API-Backend (Frontend ist SPA oder Mobile App)
  • Sie bauen die Auth-UI selbst, ohne Starter-Kit
  • Sie möchten E-Mail-Benachrichtigungen oder Reset-URLs vollständig anpassen
Wenn Sie das Projekt mit einem Starter-Kit erstellt haben (laravel new), ist die Passwort-Reset-Funktion bereits implementiert. Diese Seite beschreibt die Umsetzung ohne Starter-Kit.
Der gesamte Ablauf sieht so aus:

Konfiguration

Die Einstellungen für das Zurücksetzen von Passwörtern werden in config/auth.php unter dem Schlüssel passwords verwaltet.
// config/auth.php

'passwords' => [
    'users' => [
        'driver' => 'database',
        'provider' => 'users',
        'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
        'expire' => 60,
        'throttle' => 60,
    ],
],
  • driver — Speicherart (database oder cache)
  • expire — Gültigkeit des Tokens in Minuten. Standard: 60 Minuten
  • throttle — Wartezeit bis zum nächsten Sendeversuch (in Sekunden)

Treiber

database-Treiber

Der Standardtreiber. Die Reset-Tokens werden in der Datenbanktabelle password_reset_tokens gespeichert. Diese Tabelle ist in der Standardmigration von Laravel (0001_01_01_000000_create_users_table.php) enthalten.
'passwords' => [
    'users' => [
        'driver' => 'database',
        'provider' => 'users',
        'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
        'expire' => 60,
        'throttle' => 60,
    ],
],

cache-Treiber

Diese Option ist ab Laravel 11 verfügbar. Da keine Datenbanktabelle nötig ist, können Sie das Zurücksetzen von Passwörtern mit einem schlanken Setup implementieren.
Der cache-Treiber speichert Tokens in einem Cache-Store. Die Migration für password_reset_tokens entfällt. Tokens werden unter dem Schlüssel „E-Mail-Adresse des Benutzers“ abgelegt – nutzen Sie daher an anderer Stelle in der App nicht dieselbe E-Mail-Adresse als Cache-Schlüssel.
'passwords' => [
    'users' => [
        'driver' => 'cache',
        'provider' => 'users',
        'store' => 'passwords', // optional: dedizierter Cache-Store
        'expire' => 60,
        'throttle' => 60,
    ],
],
Geben Sie im Schlüssel store einen dedizierten Cache-Store an, verhindern Sie, dass Ihre Reset-Daten durch php artisan cache:clear gelöscht werden. Der Wert muss einem in config/cache.php konfigurierten Store-Namen entsprechen.

Modell vorbereiten

Damit das Zurücksetzen von Passwörtern funktioniert, braucht das Modell App\Models\User zwei Traits.
<?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ötig, um E-Mail-Benachrichtigungen zu versenden
  • CanResetPassword — stellt Methoden zum Erzeugen und Prüfen von Reset-Tokens bereit
Das Standardmodell User von Laravel enthält diese Traits bereits. Bei einer Neuinstallation müssen Sie nichts hinzufügen.

Routen umsetzen

Das Zurücksetzen von Passwörtern benötigt vier Routen. Zeigt ein Formular an, in dem der Benutzer die E-Mail-Adresse eingibt.
// routes/web.php

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

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

    <div>
        <label for="email">E-Mail-Adresse</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">Reset-Link senden</button>
</form>
Nimmt das Formular entgegen und versendet mit Password::sendResetLink() die Reset-E-Mail.
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() gibt einen Status-String zurück.
Status-KonstanteBeschreibung
Password::ResetLinkSentReset-Link wurde gesendet
Password::INVALID_USERKein Benutzer mit dieser E-Mail-Adresse gefunden
Password::RESET_THROTTLEDDer Versand ist begrenzt (Throttling)

3. Passwort-Reset-Formular

Zeigt dem Benutzer, der den Link in der E-Mail geklickt hat, ein Formular zur Eingabe eines neuen Passworts an.
Route::get('/reset-password/{token}', function (string $token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');
Zugehörige Blade-View:
{{-- 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">E-Mail-Adresse</label>
        <input id="email" type="email" name="email" value="{{ old('email') }}" required autofocus>
        @error('email')
            <span>{{ $message }}</span>
        @enderror
    </div>

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

    <div>
        <label for="password_confirmation">Passwort bestätigen</label>
        <input id="password_confirmation" type="password" name="password_confirmation" required>
    </div>

    <button type="submit">Passwort zurücksetzen</button>
</form>

4. Passwort-Reset ausführen

Nimmt das Formular entgegen und aktualisiert mit Password::reset() das Passwort.
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');
Status-Konstanten von Password::reset():
Status-KonstanteBeschreibung
Password::PasswordResetPasswort-Reset erfolgreich
Password::INVALID_TOKENToken ungültig oder abgelaufen
Password::INVALID_USERKein Benutzer mit dieser E-Mail-Adresse gefunden

Token-Gültigkeit

Über die Option expire in config/auth.php legen Sie die Gültigkeit des Tokens in Minuten fest. Standard: 60 Minuten.
'passwords' => [
    'users' => [
        'driver' => 'database',
        'expire' => 60, // Läuft nach 60 Minuten ab
        'throttle' => 60,
    ],
],
Beim database-Treiber bleiben abgelaufene Tokens in der Datenbank stehen. Mit folgendem Artisan-Befehl räumen Sie sie regelmäßig auf.
php artisan auth:clear-resets
Am besten automatisieren Sie das über den Scheduler.
use Illuminate\Support\Facades\Schedule;

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

Anpassungen

Eigene Benachrichtigung

Um die Reset-E-Mail anzupassen, überschreiben Sie im User-Modell die Methode sendPasswordResetNotification.
use App\Notifications\ResetPasswordNotification;

class User extends Authenticatable
{
    use Notifiable, CanResetPassword;

    /**
     * Passwort-Reset-Benachrichtigung senden
     */
    public function sendPasswordResetNotification($token): void
    {
        $url = 'https://example.com/reset-password?token='.$token;

        $this->notify(new ResetPasswordNotification($url));
    }
}
Mit ResetPassword::createUrlUsing() in der Methode boot des AppServiceProvider ändern Sie die URL des Reset-Links. Nützlich, wenn Sie – etwa bei einem SPA – auf ein anderes Frontend-Origin weiterleiten möchten.
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;
    });
}

Trusted Hosts konfigurieren

Die Reset-URL wird aus dem Host-Header des HTTP-Requests aufgebaut. Um Requests von unerlaubten Hosts zu unterbinden, empfehlen wir die Konfiguration von Trusted Hosts in bootstrap/app.php.
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustHosts(at: ['example.com']);
})
Wenn Sie das Zurücksetzen von Passwörtern anbieten, prüfen Sie unbedingt Ihre Trusted-Hosts-Konfiguration. Eine unzureichende Konfiguration birgt das Risiko einer Host-Header-Injection.

Zusammenfassung

ZielVorgehen
Reset-Link versendenPassword::sendResetLink(['email' => $email])
Passwort zurücksetzenPassword::reset($credentials, $callback)
Reset ohne Datenbanktabellecache-Treiber konfigurieren
Abgelaufene Tokens entfernenphp artisan auth:clear-resets
E-Mail-Benachrichtigung anpassensendPasswordResetNotification überschreiben
Reset-URL anpassenResetPassword::createUrlUsing()

Nächste Schritte

Einführung in Authentifizierung

Verstehen Sie das gesamte Authentifizierungssystem von Laravel.

Notifications

Erfahren Sie mehr zum Anpassen von E-Mail-Benachrichtigungen.
Zuletzt geändert am 13. Juli 2026