> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Autorisierung (Gates und Policies)

> Erläutert, wie Sie Berechtigungen für Benutzeraktionen mit Laravels Gates und Policies verwalten.

## Unterschied zwischen Authentifizierung und Autorisierung

**Authentifizierung** stellt fest, „wer" ein Benutzer ist. Der Login-Vorgang ist das klassische Beispiel.
**Autorisierung** entscheidet, „was" dieser Benutzer tun darf. Etwa: dass Benutzer nur ihre eigenen Beiträge bearbeiten dürfen oder dass Einstellungen nur von Administratoren geändert werden können.

Nachdem Sie mit der [Authentifizierung](./authentication) die Anmeldung implementiert haben, folgt als nächster Schritt die Autorisierung.

<Info>
  Für die Autorisierung bietet Laravel zwei Ansätze: Gates und Policies. Welchen Sie einsetzen, hängt vom Anwendungsfall ab.
</Info>

**Entscheidungshilfe**

| Szenario                                                                   | Empfehlung |
| -------------------------------------------------------------------------- | ---------- |
| Einfache Prüfung ohne Bezug auf ein bestimmtes Model                       | Gate       |
| Berechtigungen für CRUD-Operationen an einem Model                         | Policy     |
| Zugriffssteuerung für ein Admin-Dashboard                                  | Gate       |
| Berechtigungen für das Erstellen, Bearbeiten und Löschen von Blogbeiträgen | Policy     |

## Gates

Ein Gate ist eine schlanke, auf Closures basierende Autorisierungsprüfung. Es eignet sich für Berechtigungsentscheidungen, die nicht an ein bestimmtes Model gebunden sind.

### Autorisierungsablauf mit einem Gate

```mermaid theme={null}
flowchart TD
    A["AppServiceProvider::boot()<br>(App\\Providers\\AppServiceProvider)"] --> B["Gate::define('ability', fn)<br>Autorisierungslogik registrieren"]
    C["Autorisierungsprüfung aus dem Controller"] --> D{"Ist Gate::before()<br>gesetzt?"}
    D -->|"Ja"| E{"Rückgabewert von before()"}
    E -->|"true / false"| F["Ergebnis von before() als Endentscheidung nutzen"]
    E -->|"null"| G["Closure aus define() ausführen"]
    D -->|"Nein"| G
    G --> H{"Rückgabewert der Closure"}
    H -->|"true"| I["✓ Zugriff erlaubt"]
    H -->|"false"| J["✗ Zugriff verweigert"]
    F -->|"true"| I
    F -->|"false"| J
    J -->|"Gate::allows()"| K["gibt false zurück<br>→ abort(403) manuell aufrufen"]
    J -->|"Gate::authorize()"| L["AuthorizationException<br>→ automatisch 403 Forbidden"]
```

### Ein Gate definieren

Gates werden mit `Gate::define()` in der Methode `boot` von `App\Providers\AppServiceProvider` definiert.

```php theme={null}
// app/Providers/AppServiceProvider.php

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
```

Die Closure eines Gates erhält als ersten Parameter stets den aktuell authentifizierten Benutzer. Weitere Parameter können zusätzliche Informationen wie das zu prüfende Model enthalten.

### Berechtigungen mit einem Gate prüfen

Um im Controller mithilfe eines Gates zu prüfen, verwenden Sie `Gate::allows()` oder `Gate::denies()`.

```php theme={null}
use Illuminate\Support\Facades\Gate;

public function update(Request $request, Post $post): RedirectResponse
{
    if (! Gate::allows('update-post', $post)) {
        abort(403);
    }

    // Beitrag aktualisieren ...

    return redirect('/posts');
}
```

### Ausnahmen mit Gate::authorize() auslösen

Um bei fehlender Berechtigung automatisch eine 403-Antwort zu senden, verwenden Sie `Gate::authorize()`. Damit sparen Sie sich den manuellen Aufruf von `abort(403)`.

```php theme={null}
public function update(Request $request, Post $post): RedirectResponse
{
    Gate::authorize('update-post', $post);

    // Nur bei ausreichender Berechtigung erreicht die Ausführung diesen Punkt
    // Beitrag aktualisieren ...

    return redirect('/posts');
}
```

<Tip>
  `Gate::authorize()` wirft bei fehlender Berechtigung eine `Illuminate\Auth\Access\AuthorizationException`. Laravel wandelt diese automatisch in eine HTTP-403-Antwort um.
</Tip>

### Administrator-Bypass (Methode before)

Wenn Administratoren alle Berechtigungen erhalten sollen, verwenden Sie `Gate::before()`.

```php theme={null}
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    // $ability enthält den Namen des aufgerufenen Gates (z. B. 'update-post')
    Gate::before(function (User $user, string $ability) {
        if ($user->isAdministrator()) {
            return true;
        }
    });

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
```

Wenn die Closure in `before` einen Wert ungleich `null` zurückgibt, ist dieses Ergebnis die endgültige Entscheidung. Bei `null` (oder keiner Rückgabe) läuft die reguläre Gate-Prüfung weiter.

### @can / @cannot in Blade-Templates

In Templates sind die Direktiven `@can` und `@cannot` für Gate-Prüfungen praktisch.

```blade theme={null}
@can('update-post', $post)
    <a href="{{ route('posts.edit', $post) }}">Bearbeiten</a>
@endcan

@cannot('update-post', $post)
    <p>Sie haben keine Berechtigung, diesen Beitrag zu bearbeiten.</p>
@endcannot
```

## Policies

Eine Policy bündelt die Autorisierungslogik zu einem bestimmten Model in einer eigenen Klasse. Für Berechtigungen zum Anlegen, Anzeigen, Bearbeiten und Löschen eines `Post`-Models eignen sich Policies besser als Gates.

### Autorisierungsablauf mit einer Policy

```mermaid theme={null}
flowchart TD
    A["HTTP-Request"] --> B["Controller"]
    B --> C["Gate::authorize('update', $post)"]
    C --> D{"Ist PostPolicy::before()<br>definiert?"}
    D -->|"Ja"| E{"Rückgabewert von before()"}
    E -->|"true / false"| F["Ergebnis von before() als Endentscheidung nutzen"]
    E -->|"null"| G["PostPolicy::update(User, Post) ausführen"]
    D -->|"Nein"| G
    G --> H{"$user->id === $post->user_id?"}
    H -->|"true"| I["✓ Weiterverarbeitung"]
    H -->|"false"| J["✗ AuthorizationException<br>→ 403 Forbidden"]
    F -->|"true"| I
    F -->|"false"| J
```

### Eine Policy erzeugen

Erzeugen Sie eine Policy-Klasse mit dem Artisan-Befehl `make:policy`.

```shell theme={null}
php artisan make:policy PostPolicy
```

Mit der Option `--model` erstellen Sie eine Vorlage, die bereits alle CRUD-Methoden für das zugehörige Model enthält.

```shell theme={null}
php artisan make:policy PostPolicy --model=Post
```

Dies erzeugt die Datei `app/Policies/PostPolicy.php`.

### Automatische Erkennung von Model und Policy

Laravel erkennt Policies standardmäßig anhand einer Namenskonvention automatisch.

* Model: `app/Models/Post.php`
* Policy: `app/Policies/PostPolicy.php`

Wenn Sie diese Konvention einhalten, entfällt das explizite Registrieren der Policy.

<Info>
  Wenn Sie die Konvention nicht einhalten oder die Policy manuell registrieren möchten, verwenden Sie `Gate::policy()` in der `boot`-Methode des `AppServiceProvider`.

  ```php theme={null}
  use App\Models\Post;
  use App\Policies\PostPolicy;
  use Illuminate\Support\Facades\Gate;

  Gate::policy(Post::class, PostPolicy::class);
  ```

  In Laravel 13 können Sie die Zuordnung auch deklarativ über das Attribut `#[UsePolicy]` am Model festlegen.

  ```php theme={null}
  use App\Policies\PostPolicy;
  use Illuminate\Database\Eloquent\Attributes\UsePolicy;

  #[UsePolicy(PostPolicy::class)]
  class Post extends Model {}
  ```
</Info>

### Policy-Methoden implementieren

Eine mit `--model` erzeugte Policy enthält Methoden, die den üblichen CRUD-Aktionen entsprechen.

```php theme={null}
<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Darf der Benutzer die Beitragsübersicht ansehen?
     */
    public function viewAny(User $user): bool
    {
        return true; // Jeder authentifizierte Benutzer darf die Übersicht sehen
    }

    /**
     * Darf der Benutzer einen bestimmten Beitrag ansehen?
     */
    public function view(User $user, Post $post): bool
    {
        return true; // Jeder authentifizierte Benutzer darf den Beitrag sehen
    }

    /**
     * Darf der Benutzer einen Beitrag erstellen?
     */
    public function create(User $user): bool
    {
        return true; // Jeder authentifizierte Benutzer darf posten
    }

    /**
     * Darf der Benutzer einen Beitrag bearbeiten?
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Nur eigene Beiträge dürfen bearbeitet werden
    }

    /**
     * Darf der Benutzer einen Beitrag löschen?
     */
    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Nur eigene Beiträge dürfen gelöscht werden
    }
}
```

### Administrator-Bypass (Methode before)

Auch in einer Policy können Sie mit einer `before`-Methode Administratoren pauschal alle Berechtigungen erteilen.

```php theme={null}
/**
 * Vorabprüfung, die vor allen anderen Policy-Methoden ausgeführt wird.
 * $ability enthält den Namen der Policy-Methode (z. B. 'update' oder 'delete').
 */
public function before(User $user, string $ability): bool|null
{
    if ($user->isAdministrator()) {
        return true; // Administratoren dürfen alles
    }

    return null; // Rückgabe null → Ausführung der regulären Policy-Methode
}
```

<Warning>
  Die `before`-Methode wird nur aufgerufen, wenn in der Policy-Klasse eine passende Methode existiert. Fehlt zum Beispiel die Methode `update`, wird auch `before` nicht aufgerufen.
</Warning>

### Ausführungsreihenfolge des before-Callbacks

```mermaid theme={null}
flowchart TD
    A["Autorisierungsprüfung startet<br>authorize('update', $post)"] --> B["PostPolicy::before() ausführen"]
    B --> C{"Rückgabe null?"}
    C -->|"Nicht null (true / false)"| D["Ergebnis von before() als Endentscheidung nutzen"]
    C -->|"null"| E["Reguläre Policy-Methode ausführen<br>update() / delete() usw."]
    E --> F{"Rückgabewert der Policy-Methode"}
    F -->|"true"| G["✓ Zugriff erlaubt"]
    F -->|"false"| H["✗ Zugriff verweigert → 403"]
    D -->|"true (Admin-Bypass)"| G
    D -->|"false"| H
```

## Policies im Controller nutzen

### authorize()-Methode

Der Basis-Controller von Laravel stellt die Hilfsmethode `authorize()` bereit (wenn Sie nicht vom Basis-Controller erben, verwenden Sie `Gate::authorize()`).

<Tabs>
  <Tab title="Gate::authorize()">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Gate;

    class PostController extends Controller
    {
        public function update(Request $request, Post $post): RedirectResponse
        {
            Gate::authorize('update', $post);

            // Beitrag aktualisieren ...

            return redirect()->route('posts.index');
        }

        public function store(Request $request): RedirectResponse
        {
            Gate::authorize('create', Post::class);

            // Beitrag erstellen ...

            return redirect()->route('posts.index');
        }

        public function destroy(Post $post): RedirectResponse
        {
            Gate::authorize('delete', $post);

            $post->delete();

            return redirect()->route('posts.index');
        }
    }
    ```
  </Tab>

  <Tab title="User::can() / cannot()">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;

    class PostController extends Controller
    {
        public function update(Request $request, Post $post): RedirectResponse
        {
            if ($request->user()->cannot('update', $post)) {
                abort(403);
            }

            // Beitrag aktualisieren ...

            return redirect()->route('posts.index');
        }
    }
    ```
  </Tab>
</Tabs>

### RESTful-Policies gesammelt mit authorizeResource() registrieren

Rufen Sie im Konstruktor `authorizeResource()` auf, um für jede Aktion eines Controllers automatisch die passende Policy-Methode zu verknüpfen.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Models\Post;

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }

    // Für index(), show(), create(), store(), edit(), update() und destroy()
    // wird automatisch die passende Policy-Methode angewendet
}
```

Zuordnung zwischen Controller-Aktionen und Policy-Methoden:

| Controller-Aktion  | Policy-Methode |
| ------------------ | -------------- |
| `index`            | `viewAny`      |
| `show`             | `view`         |
| `create` / `store` | `create`       |
| `edit` / `update`  | `update`       |
| `destroy`          | `delete`       |

<Tip>
  Mit `authorizeResource()` müssen Sie nicht in jeder Aktion einzeln `authorize()` aufrufen. In Kombination mit einem RESTful-Resource-Controller ist das besonders praktisch.
</Tip>

## Autorisierung per Middleware

Um Autorisierungsprüfungen auf Routen-Ebene durchzuführen, verwenden Sie die Middleware `can`.

```php theme={null}
use App\Models\Post;

// Nur Benutzer mit Berechtigung zum Aktualisieren von Beiträgen
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('can:update,post');

// Nur Benutzer mit Berechtigung zum Erstellen von Beiträgen
Route::post('/posts', [PostController::class, 'store'])
    ->middleware('can:create,App\Models\Post');
```

Eine kürzere Schreibweise mit der Methode `can`:

```php theme={null}
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->can('update', 'post');
```

## Policies in Blade-Templates verwenden

Sobald eine Policy registriert ist, werden die Blade-Direktiven `@can` und `@cannot` automatisch über die Policy ausgewertet.

```blade theme={null}
{{-- Bearbeiten-Button nur bei entsprechender Berechtigung anzeigen --}}
@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}" class="btn">Bearbeiten</a>
@endcan

{{-- Löschen-Button ebenso --}}
@can('delete', $post)
    <form method="POST" action="{{ route('posts.destroy', $post) }}">
        @csrf
        @method('DELETE')
        <button type="submit">Löschen</button>
    </form>
@endcan

{{-- Button für neuen Beitrag --}}
@can('create', App\Models\Post::class)
    <a href="{{ route('posts.create') }}">Neuer Beitrag</a>
@endcan
```

## Praxisbeispiel: Berechtigungen für Blogbeiträge

Beispiel für eine Blog-Anwendung, in der „nur der Autor eines Beitrags ihn bearbeiten und löschen darf".

<Steps>
  <Step title="Policy erzeugen">
    ```shell theme={null}
    php artisan make:policy PostPolicy --model=Post
    ```
  </Step>

  <Step title="Policy-Methoden implementieren">
    ```php theme={null}
    <?php

    namespace App\Policies;

    use App\Models\Post;
    use App\Models\User;

    class PostPolicy
    {
        /**
         * Administratoren alle Berechtigungen erteilen
         */
        public function before(User $user, string $ability): bool|null
        {
            if ($user->is_admin) {
                return true;
            }

            return null;
        }

        public function viewAny(User $user): bool
        {
            return true;
        }

        public function view(User $user, Post $post): bool
        {
            return true;
        }

        public function create(User $user): bool
        {
            return true;
        }

        public function update(User $user, Post $post): bool
        {
            return $user->id === $post->user_id;
        }

        public function delete(User $user, Post $post): bool
        {
            return $user->id === $post->user_id;
        }
    }
    ```
  </Step>

  <Step title="authorizeResource() im Controller hinzufügen">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Models\Post;
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\View\View;

    class PostController extends Controller
    {
        public function __construct()
        {
            $this->authorizeResource(Post::class, 'post');
        }

        public function index(): View
        {
            $posts = Post::latest()->paginate(10);
            return view('posts.index', compact('posts'));
        }

        public function store(Request $request): RedirectResponse
        {
            $post = $request->user()->posts()->create(
                $request->validate([
                    'title' => ['required', 'string', 'max:255'],
                    'body'  => ['required', 'string'],
                ])
            );

            return redirect()->route('posts.show', $post);
        }

        public function update(Request $request, Post $post): RedirectResponse
        {
            $post->update(
                $request->validate([
                    'title' => ['required', 'string', 'max:255'],
                    'body'  => ['required', 'string'],
                ])
            );

            return redirect()->route('posts.show', $post);
        }

        public function destroy(Post $post): RedirectResponse
        {
            $post->delete();

            return redirect()->route('posts.index');
        }
    }
    ```
  </Step>

  <Step title="Berechtigungsprüfungen im Blade-Template ergänzen">
    ```blade theme={null}
    {{-- resources/views/posts/show.blade.php --}}
    <h1>{{ $post->title }}</h1>
    <p>{{ $post->body }}</p>
    <p>Autor: {{ $post->user->name }}</p>

    @can('update', $post)
        <a href="{{ route('posts.edit', $post) }}">Bearbeiten</a>
    @endcan

    @can('delete', $post)
        <form method="POST" action="{{ route('posts.destroy', $post) }}">
            @csrf
            @method('DELETE')
            <button type="submit">Löschen</button>
        </form>
    @endcan
    ```
  </Step>
</Steps>

## Zusammenfassung

<AccordionGroup>
  <Accordion title="Wann Gate, wann Policy?">
    * **Gate**: einfache Berechtigungsentscheidungen ohne Model-Bezug, zum Beispiel für den Zugriff auf ein Admin-Dashboard oder für globale Konfigurationsrechte.
    * **Policy**: Berechtigungen für CRUD-Operationen an einem Model. Legen Sie pro Ressource wie `Post`, `Order` oder `Comment` eine Policy-Klasse an.
  </Accordion>

  <Accordion title="Häufig genutzte API">
    ```php theme={null}
    // Prüfung über ein Gate
    Gate::allows('update-post', $post);      // true/false
    Gate::denies('update-post', $post);      // true/false
    Gate::authorize('update-post', $post);   // Ausnahme bei fehlender Berechtigung

    // Prüfung am User-Model
    $user->can('update', $post);     // true/false
    $user->cannot('update', $post);  // true/false

    // Prüfung im Controller
    Gate::authorize('update', $post);        // 403 bei fehlender Berechtigung

    // Prüfung in Blade
    @can('update', $post) ... @endcan
    @cannot('update', $post) ... @endcannot
    ```
  </Accordion>

  <Accordion title="Häufig genutzte Artisan-Befehle">
    ```shell theme={null}
    # Leere Policy erzeugen
    php artisan make:policy PostPolicy

    # Mit passenden CRUD-Methoden für das Model erzeugen
    php artisan make:policy PostPolicy --model=Post
    ```
  </Accordion>
</AccordionGroup>


## Related topics

- [Verschlüsselung (Encryption)](/de/encryption.md)
- [Laravel Telescope](/de/telescope.md)
- [Fehlerbehandlung](/de/error-handling.md)
- [Laravel Horizon](/de/horizon.md)
- [Laravel MCP](/de/mcp.md)
