presseportale/app/Http/Responses/RoleAwareLoginResponse.php
Kevin Adametz ae79d5bee4 Security: JSON-Login durchläuft die is_active-/Verifizierungschecks
RoleAwareLoginResponse gab bei wantsJson() sofort 204 zurück – VOR den
Sicherheitschecks. Ein XHR/JSON-Login eines verifiziert-inaktiven Accounts
erhielt damit eine Session ohne Logout. Checks laufen jetzt zuerst:
verifiziert-inaktiv → Logout + Session-Invalidate + 403 (JSON) bzw. Login mit
Fehler (HTML); unverifiziert → 204 (JSON) bzw. Notice (HTML); danach der
Erfolgsfall.

Tests: JSON-Login eines inaktiven Accounts (403, guest), JSON-Login eines
aktiven Users (204, authentifiziert).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 10:19:32 +00:00

61 lines
2.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Responses;
use App\Support\LoginRedirect;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;
/**
* Einheitliche Antwort für den Fortify-POST-Login (HTML und JSON/XHR) UND den
* Abschluss der 2FA-Challenge. Spiegelt dieselbe Policy wie der Volt-Login:
* - verifiziert, aber inaktiv → Session beenden, KEIN Login (auch für JSON)
* - unverifiziert → Verifizierungs-Notice (JSON: 204, verified-Middleware schützt)
* - sonst rollengerechter, 403-sicherer Redirect (intended nur wenn erreichbar)
*
* Wichtig: Die Sicherheitsprüfungen laufen VOR dem JSON-Kurzschluss, damit ein
* XHR-Login keine Session für einen deaktivierten Account erhält.
*/
class RoleAwareLoginResponse implements LoginResponseContract, TwoFactorLoginResponseContract
{
public function toResponse($request): RedirectResponse|JsonResponse
{
$user = $request->user();
$wantsJson = $request instanceof Request && $request->wantsJson();
// Sicherheits-Boundary zuerst: ein verifizierter, aber deaktivierter
// Account darf keine Session behalten egal ob HTML oder JSON.
if ($user && $user->hasVerifiedEmail() && ! $user->is_active) {
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
$message = __('Ihr Konto ist nicht aktiv. Bitte wenden Sie sich an den Support.');
return $wantsJson
? new JsonResponse(['message' => $message], 403)
: redirect()->route('login')->withErrors(['email' => $message]);
}
// Unverifizierte Selbst-Registrierer sind authentifiziert, aber die
// verified-Middleware sperrt geschützte Routen. HTML → Notice, JSON → 204.
if ($user && ! $user->hasVerifiedEmail()) {
return $wantsJson
? new JsonResponse('', 204)
: redirect()->route('verification.notice');
}
if ($wantsJson) {
return new JsonResponse('', 204);
}
$default = LoginRedirect::homeFor($user);
$intended = $request->session()->pull('url.intended');
return redirect(LoginRedirect::safeTarget($user, $intended, $default));
}
}