presseportale/app/Http/Middleware/EnsureSessionIsNotRevoked.php
Kevin Adametz 1ccb4a8479 auth/security: API-Firmenzuordnung nur für Mitglieder oder Allowlist, Google-Vorabübernahme geschlossen, gemeinsamer Login-Abschluss (Umsetzungsaudit 29.09.: R-01, K-04, K-07, K-08, B-10)
- R-01: ApiNewsroomAssignment hängt an eine bestehende Firma nur noch Owner,
  Mitglieder oder Nutzer aus NEWSROOM_API_ASSIGNMENT_USER_IDS; Pivot mit
  granted_via = api; Befehl company-memberships:api-assignments (Liste,
  --remove mit Vorschau)
- K-04: OAuth-Verifikation eines offenen Kontos verwirft Passwort,
  remember_token und Sanctum-Tokens; SessionRevocation + Middleware
  EnsureSessionIsNotRevoked widerruft alte Sessions (Redis-tauglich)
- K-08: LoginCompletion für Passwort, Magic Link und Google — last_login_at
  und Anmeldemethode auch nach 2FA, Landeziel über die Challenge, Google
  ohne erzwungenes remember, magic-login ohne guest für eigene Links
- B-10: eigener Magic-Link-Zweck image_confirmation (Migration)
- K-07: legalAcceptanceVersions #[Locked], Versionswechsel beim Absenden
  wird abgelehnt, Gate-Abfragen je Request zwischengespeichert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:09:00 +00:00

52 lines
1.5 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Services\Auth\SessionRevocation;
use Closure;
use Illuminate\Auth\SessionGuard;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
/**
* Meldet eine Session ab, die vor der letzten Sperre ihres Kontos entstanden
* ist (SessionRevocation, Audit K-04). Kostet je angemeldetem Request einen
* Cache-Zugriff; Gäste lösen keinen aus.
*/
class EnsureSessionIsNotRevoked
{
public function __construct(private readonly SessionRevocation $revocation) {}
public function handle(Request $request, Closure $next): Response
{
if (! $request->hasSession()) {
return $next($request);
}
/** @var SessionGuard $guard */
$guard = Auth::guard('web');
if (! $guard->hasUser() && ! $request->session()->has($guard->getName())) {
return $next($request);
}
$user = $guard->user();
if ($user === null || ! $this->revocation->isRevoked((int) $user->getAuthIdentifier(), $request->session())) {
return $next($request);
}
// Ohne logout(): das würde remember_token erneut rotieren und damit
// auch die gerade gültige Anmeldung des Kontoinhabers treffen.
$guard->logoutCurrentDevice();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($request->expectsJson()) {
abort(401);
}
return redirect()->guest(route('login'));
}
}