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

# Laravel Sentinel — verkenning van de routebeschermings-middleware

> De broncode van de package laravel/sentinel ontrafeld. We leggen uit hoe deze drivergebaseerde routebeschermings-middleware beheertools zoals Telescope, Horizon en Pulse beschermt.

<Info>
  Dit artikel is gebaseerd op onderzoek van de broncode (de branch `1.x`). Officiële documentatie bestaat nog niet en de package is nog niet officieel uitgebracht (per april 2026).
</Info>

## Wat is Sentinel

[Laravel Sentinel](https://github.com/laravel/sentinel) is een security-middleware-package die de toegang tot routes drivergebaseerd regelt. De package is ontwikkeld door Taylor Otwell en Mior Muhammad Zaki en ondersteunt PHP ^8.0 / Laravel 8 t/m 13.

De belangrijkste toepassing is het beschermen van routes voor beheertools zoals Telescope, Horizon en Pulse. Door simpelweg de `SentinelMiddleware` op een route toe te passen, wordt de toegang gecontroleerd met de autorisatielogica die de driver definieert.

```mermaid theme={null}
graph TD
    A["HTTP-request"] --> B["SentinelMiddleware"]
    B --> C["Sentinel Facade"]
    C --> D["SentinelManager<br>(Illuminate\\Support\\Manager)"]
    D --> E["Driver oplossen<br>driverOrFallback()"]
    E --> F["Driver#authorize()"]
    F -->|true| G["Naar de volgende middleware"]
    F -->|false| H["abort 401"]
```

## Vergelijking met de traditionele aanpak

Telescope en Horizon hadden elk een eigen autorisatiemechanisme op basis van een `gate`.

```php theme={null}
// Traditionele aanpak (bijv. TelescopeServiceProvider)
Gate::before(function ($user) {
    return $user->isAdmin() ? true : null;
});
```

Deze aanpak is afhankelijk van de authenticatiestatus van de gebruiker, met als probleem dat er "zonder login geen oordeel mogelijk is". Omdat Sentinel als middleware werkt, kan het de toegang per request regelen, ongeacht of er authenticatie is. Bovendien kun je op één plek regels definiëren voor meerdere beheertools.

## Installatie

```bash theme={null}
composer require laravel/sentinel
```

Omdat `SentinelServiceProvider` is geregistreerd in `extra.laravel.providers` van `composer.json`, wordt de serviceprovider automatisch gedetecteerd. Het publiceren van extra configuratiebestanden is niet nodig.

## De architectuur van de package

```mermaid theme={null}
classDiagram
    class Sentinel {
        +static getFacadeAccessor()
    }
    class SentinelManager {
        +createLaravelDriver() Laravel
        +getDefaultDriver() string
        +driverOrFallback(?string driver) mixed
        +extend(string driver, Closure callback) SentinelManager
    }
    class Driver {
        #Closure applicationResolver
        +authorize(Request request) bool*
        +authorizeOrFail(Request request) void
        #authorizeAccessingViaReverseProxies(Request request) bool
        #isRunningOnDockerLocally(Request request) bool
        #isPrivateIp(string requestIp) bool
        #app() Application
    }
    class Laravel {
        +authorize(Request request) bool
    }
    class SentinelMiddleware {
        +handle(Request request, Closure next, ?string driver) mixed
    }

    Sentinel --> SentinelManager : Facade
    SentinelManager --|> Manager
    Laravel --|> Driver
    SentinelMiddleware --> Sentinel : gebruikt
```

## Gedrag van de standaarddriver (de Laravel-driver)

De standaard `Laravel`-driver voert **alleen in de lokale omgeving (`APP_ENV=local`)** controles uit.

```php theme={null}
// src/Drivers/Laravel.php
public function authorize(Request $request): bool
{
    if (! $this->app()->environment('local')) {
        return true; // Buiten local altijd toestaan
    }

    // Waarschuwing bij toegang via een tunnelingdienst
    if ($this->isPrivateIp($request->ip())
        && ! $request->isFromTrustedProxy()
        && Str::endsWith($request->host(), ['.sharedwithexpose.com', '.ngrok-free.app', '.ngrok.io'])) {
        throw new RuntimeException(
            'Unable to access "..." using "local" environment, ...'
        );
    }

    // Lokale Docker-omgeving toestaan
    if ($this->isRunningOnDockerLocally($request)) {
        return true;
    }

    // Toegang via reverse proxy's controleren
    return $this->authorizeAccessingViaReverseProxies($request);
}
```

Samengevat ziet de flow er zo uit:

```mermaid theme={null}
flowchart TD
    A[Request ontvangen] --> B{Is dit de local-omgeving?}
    B -->|No| C[true teruggeven<br>（altijd toestaan）]
    B -->|Yes| D{Privé-IP én<br>buiten trustedProxy én<br>een tunnelingdienst?}
    D -->|Yes| E[RuntimeException gooien<br>met configuratie-instructies]
    D -->|No| F{Lokale Docker-omgeving?<br>127.0.0.1 + .dockerenv}
    F -->|Yes| G[true teruggeven<br>（toestaan）]
    F -->|No| H{Geen privé-IP én<br>via trustedProxy?}
    H -->|Yes| I[false teruggeven<br>（blokkeren）]
    H -->|No| J[true teruggeven<br>（toestaan）]
```

<Warning>
  De `Laravel`-driver geeft buiten de `local`-omgeving altijd `true` (toestaan) terug. Heb je toegangscontrole in productie nodig, maak dan een custom driver.
</Warning>

### Privé-IP's herkennen

De methode `isPrivateIp()` van de basisklasse `Driver` gebruikt Symfony's `IpUtils` en beschouwt de volgende IP-reeksen als privé-IP's.

| Reeks            | Beschrijving         |
| ---------------- | -------------------- |
| `127.0.0.0/8`    | Loopback (RFC1700)   |
| `10.0.0.0/8`     | Privé (RFC1918)      |
| `192.168.0.0/16` | Privé (RFC1918)      |
| `172.16.0.0/12`  | Privé (RFC1918)      |
| `169.254.0.0/16` | Link-local (RFC3927) |
| `::1/128`        | IPv6-loopback        |
| `fc00::/7`       | IPv6 unique local    |
| `fe80::/10`      | IPv6 link-local      |

### Een lokale Docker-omgeving detecteren

```php theme={null}
// src/Drivers/Driver.php
protected function isRunningOnDockerLocally(Request $request): bool
{
    return $request->server->get('REMOTE_ADDR') === '127.0.0.1'
        && file_exists(base_path('.dockerenv'));
}
```

Als `REMOTE_ADDR` gelijk is aan `127.0.0.1` én er een `.dockerenv`-bestand in de projectroot bestaat, wordt dit als een lokale Docker-omgeving beschouwd.

## Gebruiken als middleware

### Basisgebruik

```php theme={null}
use Laravel\Sentinel\Http\Middleware\SentinelMiddleware;

Route::middleware(SentinelMiddleware::class)->group(function () {
    Route::get('/telescope', function () { /* ... */ });
    Route::get('/horizon', function () { /* ... */ });
    Route::get('/pulse', function () { /* ... */ });
});
```

### Een driver opgeven

Je kunt een drivernaam meegeven als middleware-argument. Geef je een niet-bestaande drivernaam op, dan valt de package terug op de standaarddriver (het gedrag van `driverOrFallback()`).

```php theme={null}
Route::middleware([SentinelMiddleware::class . ':custom-driver'])->group(function () {
    // Autorisatie met een custom driver
});
```

### De implementatie van de middleware

```php theme={null}
// src/Http/Middleware/SentinelMiddleware.php
public function handle(Request $request, Closure $next, ?string $driver = null)
{
    abort_unless(Sentinel::driverOrFallback($driver)->authorize($request), 401);

    return $next($request);
}
```

Geeft `authorize()` `false` terug, dan wordt de request afgebroken met HTTP 401. Met `Driver::authorizeOrFail()` kun je ook een `AuthorizationException` laten gooien (de middleware zelf gebruikt die niet).

## Een custom driver maken

Je maakt een custom driver door de abstracte klasse `Driver` te extenden en de methode `authorize()` te implementeren.

```php theme={null}
use Laravel\Sentinel\Sentinel;
use Laravel\Sentinel\Drivers\Driver;
use Illuminate\Http\Request;

Sentinel::extend('admin-only', function ($app) {
    return new class extends Driver {
        public function authorize(Request $request): bool
        {
            // Alleen geauthenticeerde gebruikers met de rol admin toestaan
            $user = $request->user();

            return $user !== null && $user->hasRole('admin');
        }
    };
});
```

Registreer `extend()` bijvoorbeeld in `AppServiceProvider::boot()`.

### De utilitymethodes van de basisklasse benutten

De klasse `Driver` biedt handige methodes zoals IP-controles, die je vrij kunt gebruiken vanuit je custom driver.

```php theme={null}
public function authorize(Request $request): bool
{
    // In productie alleen toegang vanaf privé-IP's toestaan
    if ($this->app()->environment('production')) {
        return $this->isPrivateIp($request->ip());
    }

    // Lokaal alleen Docker of directe toegang
    return $this->isRunningOnDockerLocally($request)
        || $this->authorizeAccessingViaReverseProxies($request);
}
```

## Hoe SentinelManager werkt

`SentinelManager` extendt `Illuminate\Support\Manager`. `Manager` is de basisklasse van Laravel voor het implementeren van het driverpatroon; via `driver()` worden driverinstanties opgelost en gecachet.

```php theme={null}
// src/SentinelManager.php
class SentinelManager extends Manager
{
    protected function createLaravelDriver()
    {
        return new Laravel(fn () => $this->getContainer());
    }

    public function getDefaultDriver()
    {
        return 'laravel';
    }

    public function driverOrFallback(?string $driver)
    {
        return rescue(
            fn () => $this->driver($driver),
            value(fn () => $this->driver()),
            false  // Niet naar de log schrijven
        );
    }
}
```

Omdat `driverOrFallback()` stilletjes terugvalt op de standaarddriver wanneer de opgegeven driver niet wordt gevonden, levert een niet-bestaande drivernaam als middleware-argument geen fout op.

`SentinelManager` wordt door de `SentinelServiceProvider` geregistreerd als scoped singleton (`scoped`), zodat de driverinstantie binnen één request wordt hergebruikt.

```php theme={null}
// src/SentinelServiceProvider.php
public function register(): void
{
    $this->app->scoped(SentinelManager::class, fn ($app) => new SentinelManager($app));
}
```

## Samenvatting

`laravel/sentinel` is een kleine package, maar dankzij het driverpatroon op basis van `Illuminate\Support\Manager` is hij zeer goed uitbreidbaar.

| Onderdeel           | Inhoud                                  |
| ------------------- | --------------------------------------- |
| Versie              | 1.x                                     |
| Ondersteund PHP     | ^8.0                                    |
| Ondersteund Laravel | 8 t/m 13                                |
| Standaarddriver     | Controleert alleen in de local-omgeving |
| Custom drivers      | Toe te voegen met `Sentinel::extend()`  |

De standaard `Laravel`-driver is gespecialiseerd in het blokkeren van toegang via tunnelingdiensten tijdens lokale ontwikkeling; voor bescherming in productie moet je een eigen custom driver maken. Zodra de officiële documentatie er is, zullen concretere gebruikspatronen duidelijk worden.

<Card title="laravel/sentinel repository" icon="github" href="https://github.com/laravel/sentinel">
  De broncode en de nieuwste wijzigingen vind je in de branch `1.x` op GitHub.
</Card>


## Related topics

- [Eerste verkenning van Laravel Passkeys (passkeys-server + @laravel/passkeys)](/nl/blog/passkeys-introduction.md)
- [Middleware](/nl/middleware.md)
- [laravel/symfony-on-cloud — Symfony-apps draaien op Laravel Cloud](/nl/blog/symfony-on-cloud-introduction.md)
- [Laravel Multiplex — een TUI om lokale ontwikkelprocessen samen te beheren](/nl/blog/multiplex-introduction.md)
- [Laravel Fortify en de starter kits](/nl/advanced/fortify.md)
