51 lines
1.5 KiB
PHP
51 lines
1.5 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace Modules\Core\Auth\Http\Middleware;
|
||
|
|
|
||
|
|
use Closure;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\Support\Facades\Auth;
|
||
|
|
use Modules\Core\Auth\Services\UserSessionService;
|
||
|
|
use Symfony\Component\HttpFoundation\Response;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The enforcement half of the session registry — see
|
||
|
|
* Modules\Core\Auth\Services\UserSessionService's own docblock. Not
|
||
|
|
* auto-registered anywhere (no routes/kernel wiring exist in this
|
||
|
|
* package — see Modules\Core\Customer\Services\CustomerAccountService's
|
||
|
|
* own docblock for why this branch stops at services); a consuming app
|
||
|
|
* adds this to its `web` middleware group (after `auth`) to actually get
|
||
|
|
* "logout everywhere" enforcement.
|
||
|
|
*
|
||
|
|
* A request with no recorded UserSession at all (see
|
||
|
|
* UserSessionService::currentSession()'s own docblock) is let through —
|
||
|
|
* only an EXPLICITLY revoked session is rejected.
|
||
|
|
*/
|
||
|
|
class EnsureSessionNotRevoked
|
||
|
|
{
|
||
|
|
public function __construct(
|
||
|
|
private readonly UserSessionService $sessions,
|
||
|
|
) {}
|
||
|
|
|
||
|
|
public function handle(Request $request, Closure $next): Response
|
||
|
|
{
|
||
|
|
if (! Auth::check()) {
|
||
|
|
return $next($request);
|
||
|
|
}
|
||
|
|
|
||
|
|
$session = $this->sessions->currentSession();
|
||
|
|
|
||
|
|
if ($session && $session->isRevoked()) {
|
||
|
|
Auth::logout();
|
||
|
|
$request->session()->invalidate();
|
||
|
|
$request->session()->regenerateToken();
|
||
|
|
|
||
|
|
abort(401, 'Your session has been revoked. Please log in again.');
|
||
|
|
}
|
||
|
|
|
||
|
|
$session?->update(['last_used_at' => now()]);
|
||
|
|
|
||
|
|
return $next($request);
|
||
|
|
}
|
||
|
|
}
|